View mode: basic / threaded / horizontal-split · Log in · Help
April 30, 2012
Help: running a method from the importing file's method "space"
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
Re: Help: running a method from the importing file's method "space"
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
Re: Help: running a method from the importing file's method "space"
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
Re: Help: running a method from the importing file's method "space"
>  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
Re: Help: running a method from the importing file's method "space"
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
Re: Help: running a method from the importing file's method "space"
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
Re: Help: running a method from the importing file's method "space"
With MyLib obviously containing the MyLibInit(HINSTANCE hInst, 
HINSTANCE hPrevInst, LPSTR CmdLine,
int CmdShow) method.
May 01, 2012
Re: Help: running a method from the importing file's method "space"
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
Re: Help: running a method from the importing file's method "space"
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
Top | Discussion index | About this forum | D home