www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - How to call a dll function from D?

reply snowflake <snowflake_member pathlink.com> writes:
I've read through the docs but I can't seem to work out how to declare a
function that can to be loaded from a specific dll. The calling convention is
cdecl. Is there a sort of equivalent loadlibrary() machanism? I tried to link
the function via a lib file but the linker says "Error 43: Not a Valid Library
File", even though the file is used by other apps on the computer. 

HMS
May 02 2004
next sibling parent reply firefly fssc.demon.co.uk writes:
After I posted this message I noticed that loadlibrary and getprocaddress are
available from the windows module. Anyone got an example showing how to use the
GetProcAddress function in D?

HMS

In article <c74emg$fe2$1 digitaldaemon.com>, snowflake says...
I've read through the docs but I can't seem to work out how to declare a
function that can to be loaded from a specific dll. The calling convention is
cdecl. Is there a sort of equivalent loadlibrary() machanism? I tried to link
the function via a lib file but the linker says "Error 43: Not a Valid Library
File", even though the file is used by other apps on the computer. 

HMS

May 02 2004
parent reply Eric Anderton <Eric_member pathlink.com> writes:
After I posted this message I noticed that loadlibrary and getprocaddress are
available from the windows module. Anyone got an example showing how to use the
GetProcAddress function in D?

It just so happens that I was working on the very same thing yesterday. :) GetProcAddress returns the address of an export on the dll. You can cast this value to a function handle (see below) or a variable address if desired. More explicit information can be found at MDSN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/getprocaddress.asp The quick and dirty D version goes something like this: import std.c.windows.windows; alias (*HelloWorldHandle)(/*put your handle parameters here*/); void LoadLibraryExample(string libraryFileName){ HANDLE hLibrary; //make sure you have a trailing \0 when you cast to a c-style string! hLibrary = LoadLibraryA((char*)(libraryFileName ~ "\0")); if(hLibrary){ HelloWorldHandle helloWorld = (HelloWorldHandle)GetProcAddress(hLibrary,(char*)("HelloWorld\0")); if(!helloWorld) throw new Exception("Failure to load HelloWorld handle."); } helloWorld(/*put your handle arguments here*/); FreeLibrary(hLibrary); } else throw new Exception("Failure to load library: " ~ libraryFileName); }
May 03 2004
parent reply firefly fssc.demon.co.uk writes:
Perfect, thanks! I just sent another post but ignore it, your email answers my
question.

Herbert Sauro


In article <c75it6$26gf$1 digitaldaemon.com>, Eric Anderton says...
After I posted this message I noticed that loadlibrary and getprocaddress are
available from the windows module. Anyone got an example showing how to use the
GetProcAddress function in D?

It just so happens that I was working on the very same thing yesterday. :) GetProcAddress returns the address of an export on the dll. You can cast this

etc
May 03 2004
parent reply firefly fssc.demon.co.uk writes:
I was a bit premature in my reply, I don't understand your use of the alias
keyword, I thought alias tokk two parts, the thingk to alias and the alias name,
but in your example you only have one of these, i.e

alias (*HelloWorld)(/* args got here*/);

I don't understnd how you are declaring the function pointer type.

Herbert Sauro

In article <c76119$2sbv$1 digitaldaemon.com>, firefly fssc.demon.co.uk says...
Perfect, thanks! I just sent another post but ignore it, your email answers my
question.

Herbert Sauro


In article <c75it6$26gf$1 digitaldaemon.com>, Eric Anderton says...
After I posted this message I noticed that loadlibrary and getprocaddress are
available from the windows module. Anyone got an example showing how to use the
GetProcAddress function in D?

It just so happens that I was working on the very same thing yesterday. :) GetProcAddress returns the address of an export on the dll. You can cast this

etc

May 03 2004
parent reply Eric Anderton <Eric_member pathlink.com> writes:
I was a bit premature in my reply, I don't understand your use of the alias
keyword, I thought alias tokk two parts, the thingk to alias and the alias name,
but in your example you only have one of these, i.e

alias (*HelloWorld)(/* args got here*/);

I don't understnd how you are declaring the function pointer type.

Ack. Leave it to me to post a suggestion without compiling it first, as I didn't include the return type. It should read: alias void (*HelloWorldHandle)(/*args*/); Now, this should look like the good-old C/C++ style for a function pointer. D also provides a more succinct way of doing this (and less misunderstood syntax IMO). function(/*args*/) HelloWorldHandle; //Same thing, but no 'alias' required Hope this clears things up.
May 03 2004
parent reply firefly fssc.demon.co.uk writes:
Thanks Eric, the new syntax works for me. The only issue now I have is
specifying the calling convention, I need to specify cdecl. I'm currently
getting an access violation which I assume is due to a bad calling mechanism.

Herbert

In article <c768it$67u$1 digitaldaemon.com>, Eric Anderton says...
I was a bit premature in my reply, I don't understand your use of the alias
keyword, I thought alias tokk two parts, the thingk to alias and the alias name,
but in your example you only have one of these, i.e

alias (*HelloWorld)(/* args got here*/);

I don't understnd how you are declaring the function pointer type.

Ack. Leave it to me to post a suggestion without compiling it first, as I didn't include the return type. It should read: alias void (*HelloWorldHandle)(/*args*/); Now, this should look like the good-old C/C++ style for a function pointer. D also provides a more succinct way of doing this (and less misunderstood syntax IMO). function(/*args*/) HelloWorldHandle; //Same thing, but no 'alias' required Hope this clears things up.

May 03 2004
parent reply Eric Anderton <Eric_member pathlink.com> writes:
Thanks Eric, the new syntax works for me. The only issue now I have is
specifying the calling convention, I need to specify cdecl. I'm currently
getting an access violation which I assume is due to a bad calling mechanism.

This is just a shot in the dark, but have you tried prefixing the handle definition with "extern(C)"? extern(C) function(int foo) bar; // maybe this will create the right call type? After looking over Walter's D documentation again, I think the "extern" statement gets double-duty when compared to C/C++. Where in C we use "extern" to mean "declared later/elsewhere", D uses it for that as well as the calling convention. Add to that the fact that DMD makes multiple passes on any given source file, and it really shifts the meaning more towards being a call-type declaration. Again, no D compiler in sight until I get home... so here goes nothing, right? - Eric from: http://www.digitalmars.com/d/htomodule.html __cdecl, __pascal, __stdcall int __cdecl x; int __cdecl foo(int a); int __pascal bar(int b); int __stdcall abc(int c); become: extern (C) int x; extern (C) int foo(int a); extern (Pascal) int bar(int b); extern (Windows) int abc(int c);
May 03 2004
parent reply firefly fssc.demon.co.uk writes:
Thanks again for the help, you're the only one who has given me sensible
responses. Tonight I had an idea (don't know why I didn't think of it before), I
searched the dmd directory for GetProcAddress, and to my surprise I found a
sample file which gave an example. You were actually very close, the only thing
that was off was the alias declaration, it should have been:

extern (C) alias void (*ptr)(/* args */);

This is not particularly clear from the documentation.

Herbert

In article <c76bn6$at5$1 digitaldaemon.com>, Eric Anderton says...
Thanks Eric, the new syntax works for me. The only issue now I have is
specifying the calling convention, I need to specify cdecl. I'm currently
getting an access violation which I assume is due to a bad calling mechanism.

This is just a shot in the dark, but have you tried prefixing the handle definition with "extern(C)"? extern(C) function(int foo) bar; // maybe this will create the right call type? After looking over Walter's D documentation again, I think the "extern" statement gets double-duty when compared to C/C++. Where in C we use "extern" to mean "declared later/elsewhere", D uses it for that as well as the calling convention. Add to that the fact that DMD makes multiple passes on any given source file, and it really shifts the meaning more towards being a call-type declaration. Again, no D compiler in sight until I get home... so here goes nothing, right? - Eric from: http://www.digitalmars.com/d/htomodule.html __cdecl, __pascal, __stdcall int __cdecl x; int __cdecl foo(int a); int __pascal bar(int b); int __stdcall abc(int c); become: extern (C) int x; extern (C) int foo(int a); extern (Pascal) int bar(int b); extern (Windows) int abc(int c);

May 04 2004
parent Eric Anderton <Eric_member pathlink.com> writes:
Thanks again for the help, you're the only one who has given me sensible
responses. 

You're quite welcome. Anything to help a fellow developer. Be sure to let us (the NG) know how the project pans out.
Tonight I had an idea (don't know why I didn't think of it before), I
searched the dmd directory for GetProcAddress, and to my surprise I found a
sample file which gave an example. 

So I'm not the only one sifting through Walter's code! ::chuckle:: Lately, I've taken to pulling apart Phobos to learn more about the platform. IMO, this is the best way (at least for now) to learn how to do "undocumented" things with the D platform. And as far as source goes, its a pretty good read. ; - Eric
May 04 2004
prev sibling next sibling parent reply "Matthew" <matthew.hat stlsoft.dot.org> writes:
I've written the std.loader module, which will hopefully appear in the next
release of the compiler/library.

That doesn't help you now, though, does it?

You can just declare

extern(Windows)
{
    void *LoadLibraryA(char *libName);
    int FreeLibrary(void *hLib);
    void *GetProcAddress(void *hModule, char *procName);
}

and proceed with them

"snowflake" <snowflake_member pathlink.com> wrote in message
news:c74emg$fe2$1 digitaldaemon.com...
 I've read through the docs but I can't seem to work out how to declare a
 function that can to be loaded from a specific dll. The calling convention is
 cdecl. Is there a sort of equivalent loadlibrary() machanism? I tried to link
 the function via a lib file but the linker says "Error 43: Not a Valid Library
 File", even though the file is used by other apps on the computer.

 HMS

May 02 2004
parent firefly fssc.demon.co.uk writes:
Thanks for the information. The question now is how do I declare a function
pointer for the dll method I want to load. In C I would use:

typedef int (*ADDITIONFUNCTION)(int a,int b);
ADDITIONFUNCTION addFunction;

addFunction = (ADDITIONFUNCTION) GetProcAddress(hDll, "fnDemoDll");

Herbert Sauro

In article <c74g00$h1b$1 digitaldaemon.com>, Matthew says...
I've written the std.loader module, which will hopefully appear in the next
release of the compiler/library.

That doesn't help you now, though, does it?

You can just declare

extern(Windows)
{
    void *LoadLibraryA(char *libName);
    int FreeLibrary(void *hLib);
    void *GetProcAddress(void *hModule, char *procName);
}

and proceed with them

"snowflake" <snowflake_member pathlink.com> wrote in message
news:c74emg$fe2$1 digitaldaemon.com...
 I've read through the docs but I can't seem to work out how to declare a
 function that can to be loaded from a specific dll. The calling convention is
 cdecl. Is there a sort of equivalent loadlibrary() machanism? I tried to link
 the function via a lib file but the linker says "Error 43: Not a Valid Library
 File", even though the file is used by other apps on the computer.

 HMS


May 03 2004
prev sibling parent Achilleas Margaritis <Achilleas_member pathlink.com> writes:
In article <c74emg$fe2$1 digitaldaemon.com>, snowflake says...
I've read through the docs but I can't seem to work out how to declare a
function that can to be loaded from a specific dll. The calling convention is
cdecl. Is there a sort of equivalent loadlibrary() machanism? I tried to link
the function via a lib file but the linker says "Error 43: Not a Valid Library
File", even though the file is used by other apps on the computer. 

HMS

It seems that you want to link with a specific DLL in compile time, instead of run-time, right ? Ok, here it is: DigitalMars has a tool named 'implib.exe' which is part of the DigitalMars C/C++ compiler package which takes a DLL as an argument and produces a .lib file which can be used with the DM linker. For example, let's say you have foo.dll which contains the function int foo(int) You do the following steps: 1) execute: implib foo.dll foo.lib 2) Link with foo.lib. 3) in your program, you must have: extern(C) int foo(int); 4) use function 'foo' normally. This is how I used the Allegro DLL with D.
May 04 2004