Thread overview
Help: running a method from the importing file's method "space"
Apr 30, 2012
Rowan
Apr 30, 2012
Era Scarecrow
Apr 30, 2012
Era Scarecrow
Apr 30, 2012
Rowan
Apr 30, 2012
Rowan
Apr 30, 2012
Rowan
Apr 30, 2012
Era Scarecrow
May 01, 2012
Regan Heath
May 01, 2012
Rowan
April 30, 2012
Hi all,

Two things first:
1) I am quite new to D and have been using Java at school and a bit of C++ at home so some things confuse me. Please bear with me.
2) Apologies about the ambiguity of the title, I have no idea how to ask this in just one line so I'll elaborate here:

What I want to do is create a static library to create a small wrapper/ to the Win API GUI functions for some basic GUI components for some projects instead of using some of the already made and slightly bulky GUI libraries around for D. This is what gives me a problem explained below.

I need the WinMain(...) entry point to be run so that I can get my window handle for many of the windows GUI functions so using main() is out, and I want WinMain to be in the library, so the entry point of the program is in the library not the importing file, so if I have my (simplified) files:

--------------
File: MyLib.d:
--------------

module MyLib;

import core.runtime;
import core.sys.windows.windows;
//import std.string;

extern(windows) {
    int WinMain(...) {
        int success;
        //Init code
        success = myWin(...);
        return success;
    }
}

int myWin(...) {
    progMain();
}

//Other code...

--------------
File: test.d (i.e. importing file):
--------------

import MyLib;

pragma(lib, "MyLib.lib");

void progMain() {
    //User TODO code...
}

So if I want to make any file (in this case "test.d", which can just import MyLib after I have -lib'd it and use the custom "entry point" -> "progMain" after "MyLib" has gotten everything it needs from the WinMain entry point, so that the programmer (me) can now just import MyLib and start typing their code in progMain instead of the usual main() without having to alter the source of MyLib. Basically I want MyLib to be able to call test's "progMain()", as when I try I get some error along the lines of progMain() not existing. I hope someone understands me, if you do and have an answer could you give me a step by step way of doing this?

Thanks

-Rowan
April 30, 2012
On Monday, 30 April 2012 at 18:30:29 UTC, Rowan wrote:

> --------------
> File: MyLib.d:
> --------------
>
> module MyLib;
>
> import core.runtime;
> import core.sys.windows.windows;
> //import std.string;
>
>
> So if I want to make any file (in this case "test.d", which can just import MyLib after I have -lib'd it and use the custom "entry point" -> "progMain" after "MyLib" has gotten everything it needs from the WinMain entry point, so that the programmer (me) can now just import MyLib and start typing their code in progMain instead of the usual main() without having to alter the source of MyLib. Basically I want MyLib to be able to call test's "progMain()", as when I try I get some error along the lines of progMain() not existing. I hope someone understands me, if you do and have an answer could you give me a step by step way of doing this?

 Add 'import test;' to your MyLib module.

April 30, 2012
On Monday, 30 April 2012 at 18:50:24 UTC, Era Scarecrow wrote:
>  Add 'import test;' to your MyLib module.

 Although that seems like it's connecting a library to something it shouldn't... In which case perhaps a delegate passed to the library to call myProg? Doesn't seem right either.

 What is your library suppose to do? And why should it have to access something outside it's library set? (Unless test.d is part of the library)
April 30, 2012
>  Add 'import test;' to your MyLib module.

That does work, but I didn't want to change the source of MyLib, I dunno maybe what I'm asking isn't possible.
April 30, 2012
On Monday, 30 April 2012 at 19:22:35 UTC, Rowan wrote:
>> Add 'import test;' to your MyLib module.
>
> That does work, but I didn't want to change the source of MyLib, I dunno maybe what I'm asking isn't possible.

 Is there a reason the library needs to call outside of it's own library access? When I think of a library it's suppose to be self contained. Perhaps just the approach is wrong?
April 30, 2012
On Monday, 30 April 2012 at 18:54:41 UTC, Era Scarecrow wrote:
> On Monday, 30 April 2012 at 18:50:24 UTC, Era Scarecrow wrote:
>> Add 'import test;' to your MyLib module.
>
>  Although that seems like it's connecting a library to something it shouldn't... In which case perhaps a delegate passed to the library to call myProg? Doesn't seem right either.
>
>  What is your library suppose to do? And why should it have to access something outside it's library set? (Unless test.d is part of the library)

I make this library to create a few classes for creating some simple GUI components (window, buttons, text boxes, that's about it) as a bit of a learning exercise, and for practical use. "test.d" is not part of the library, it is just for testing the library. What I could do that would definatly work is:

--------------
File "test.d":
--------------

import core.runtime;
import core.sys.windows.windows;
import MyLib;

pragma(lib, "MyLib.lib);

extern(Windows) {
    WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR CmdLine, int CmdShow) {
        MyLibInit(hInst, hPrevInst, CmdLine, CmdShow);
    }

----ENDFILE----

So I can then just pass everything my lib requires to it and then there is no need for progMain. I'm asking this question as with QT's source, it uses WinMain: https://qt.gitorious.org/qt/qt/blobs/HEAD/src/winmain/qtmain_win.cpp

80	/*
81	  WinMain() - Initializes Windows and calls user's startup function main().
82	  NOTE: WinMain() won't be called if the application was linked as a "console"
83	  application.
84	*/
85	
86	#ifdef Q_OS_WINCE
87	int WINAPI WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPWSTR /*wCmdParam*/, int cmdShow)

Yet you can still use "main()" from your program and then link to QT's dll and use its functionality. I know that is C++ but that's where I'm comming from with this.

I think you are right and my library isn't supposed to try access "test.d"'s methods, classes, etc. and be self contained. So should I rather go with the WinMain in my main program then pass the parameters to MyLib like I showed before the QT reference?
April 30, 2012
With MyLib obviously containing the MyLibInit(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR CmdLine,
int CmdShow) method.
May 01, 2012
I'm not sure if any of this is helpful but I've had a tinker and had some
measure of success :p

I think you have the following issues to resolve:
1. When you build the lib, you need to tell it that the progMain symbol is
to be found 'extern'ally.
2. When you build the exe, you have to make sure the linker goes looking
for WinMain and not main /and/ that it looks in the lib for it.

I've managed to get something "working" but it's not what you want (but it
might help you get there) and it's not pretty...

1. Add the following line to mylib.d:
            extern(C) int progMain();

            This tells dmd that when it compiles mylib.d the symbol progMain
is
to
be found externally, and it's C linkage (I tried D linkage, but this
prepends "MyLib" to the symbol it searches for).

2. Modify test.d and make it read:
            extern(C)
            void progMain() {

            This makes progMain a C linkage symbol, which the linker will
find
and
use.

3. Compile mylib.d with:
             dmd -c mylib

            (I know, this doesn't build a lib more on that later..)

4. Compile test.d with:
             dmd -c test

5. Run link.exe manually, e.g.

            <path to dmd bin>\link.exe
test+mylib,,nul,phobos+user32+kernel32/noi;

            This produces a test.exe which runs and executes progMain from
test.d.


Initially I was trying to get it working with a lib but I got dead-ended.

Using the code changes I mentioned above, and a test.def which reads:
            EXETYPE NT
            SUBSYSTEM WINDOWS

If you go:

            dmd -lib mylib
            dmd -c test
            link.exe test,,nul,mylib+phobos+user32+kernel32/noi,test.def;

you get:

            OPTLINK : Warning 134: No Start Address

I think that the reason for this is that test.obj does not define an entry
point, see:
            http://www.digitalmars.com/ctg/OptlinkErrorMessages.html
            (No Start Address)

This implies it is looking for entry points in object files, and perhaps
that means /not/ libs??  Not sure.


So, I tried to re-use my earlier extern trick adding:

extern(Windows)
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
int nCmdShow);

to test.d, but that gave the same results.


References..
http://dlang.org/windows.html
http://www.digitalmars.com/ctg/optlink.html
https://github.com/AndrejMitrovic/DWinProgramming

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
May 01, 2012
On Tuesday, 1 May 2012 at 17:34:23 UTC, Regan Heath wrote:
> I'm not sure if any of this is helpful but I've had a tinker and had some
> measure of success :p
>
> I think you have the following issues to resolve:
> 1. When you build the lib, you need to tell it that the progMain symbol is
> to be found 'extern'ally.
> 2. When you build the exe, you have to make sure the linker goes looking
> for WinMain and not main /and/ that it looks in the lib for it.
>
> I've managed to get something "working" but it's not what you want (but it
> might help you get there) and it's not pretty...
>
> 1. Add the following line to mylib.d:
>             extern(C) int progMain();
>
>             This tells dmd that when it compiles mylib.d the symbol progMain
> is
> to
> be found externally, and it's C linkage (I tried D linkage, but this
> prepends "MyLib" to the symbol it searches for).
>
> 2. Modify test.d and make it read:
>             extern(C)
>             void progMain() {
>
>             This makes progMain a C linkage symbol, which the linker will
> find
> and
> use.
>
> 3. Compile mylib.d with:
>              dmd -c mylib
>
>             (I know, this doesn't build a lib more on that later..)
>
> 4. Compile test.d with:
>              dmd -c test
>
> 5. Run link.exe manually, e.g.
>
>             <path to dmd bin>\link.exe
> test+mylib,,nul,phobos+user32+kernel32/noi;
>
>             This produces a test.exe which runs and executes progMain from
> test.d.
>
>
> Initially I was trying to get it working with a lib but I got dead-ended.
>
> Using the code changes I mentioned above, and a test.def which reads:
>             EXETYPE NT
>             SUBSYSTEM WINDOWS
>
> If you go:
>
>             dmd -lib mylib
>             dmd -c test
>             link.exe test,,nul,mylib+phobos+user32+kernel32/noi,test.def;
>
> you get:
>
>             OPTLINK : Warning 134: No Start Address
>
> I think that the reason for this is that test.obj does not define an entry
> point, see:
>             http://www.digitalmars.com/ctg/OptlinkErrorMessages.html
>             (No Start Address)
>
> This implies it is looking for entry points in object files, and perhaps
> that means /not/ libs??  Not sure.
>
>
> So, I tried to re-use my earlier extern trick adding:
>
> extern(Windows)
> int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
> int nCmdShow);
>
> to test.d, but that gave the same results.
>
>
> References..
> http://dlang.org/windows.html
> http://www.digitalmars.com/ctg/optlink.html
> https://github.com/AndrejMitrovic/DWinProgramming

Thank you very much for the input, I tried to do what you said
and followed your instructions and went through link.exe and did
get a successful compile. What you have done does work (tested it
by omitting the .def file in link to get the console window and
did a writeln in WinMain for mylib AND progMain for test and it
does work (both wrileln's from WinMain and progMain print to
console) :-). This is pretty much what I wanted, yet it is still,
as you put it "not pretty", and making a lib for it isn't
working. It's a bit late here, so I'll tinker around tomorrow or
the day after with this and see if I can get towards more of a
cleaner way of doing this, I'll post back here with what I find.
Once again thank you, this seems like a nudge in the right
direction.

-Rowan