www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Calling D from C++

reply Loopback <elliott.darfink gmail.com> writes:
Hello!

As of my understanding you can write usable c libraries in D by using
extern(C). The problem is that I haven't found any other threads asking
the same question about C++ (since extern for c++ exists as well). So
I have two questions, is it possible to write a dll in D usable in c++
code, and if the answer is yes, are there any restrictions?

Am I forced to use explicit memory handling, or can this be handled by
the garbage collection internally by the dll etc?
Jul 17 2011
parent reply Loopback <elliott.darfink gmail.com> writes:
On 2011-07-17 21:45, Loopback wrote:
 Hello!

 As of my understanding you can write usable c libraries in D by using
 extern(C). The problem is that I haven't found any other threads asking
 the same question about C++ (since extern for c++ exists as well). So
 I have two questions, is it possible to write a dll in D usable in c++
 code, and if the answer is yes, are there any restrictions?

 Am I forced to use explicit memory handling, or can this be handled by
 the garbage collection internally by the dll etc?
Sorry for mentioning this a bit late but noticed this now; http://www.digitalmars.com/d/2.0/cpp_interface.html Although if someone has own experiences or something interesting to say about the matter, please do.
Jul 17 2011
parent reply Johann MacDonagh <johann.macdonagh.no spam.gmail.com> writes:
On 7/17/2011 3:53 PM, Loopback wrote:
 On 2011-07-17 21:45, Loopback wrote:
 Hello!

 As of my understanding you can write usable c libraries in D by using
 extern(C). The problem is that I haven't found any other threads asking
 the same question about C++ (since extern for c++ exists as well). So
 I have two questions, is it possible to write a dll in D usable in c++
 code, and if the answer is yes, are there any restrictions?

 Am I forced to use explicit memory handling, or can this be handled by
 the garbage collection internally by the dll etc?
Sorry for mentioning this a bit late but noticed this now; http://www.digitalmars.com/d/2.0/cpp_interface.html Although if someone has own experiences or something interesting to say about the matter, please do.
I think you're going to be better off defining your D routines as extern(C) and then defining the C++ headers as __cdecl (for Windows of course). C++ can, of course, link against libraries using cdecl. If you write your D DLL with the normal DllEntry (this came from VisualD): import std.c.windows.windows; import core.dll_helper; __gshared HINSTANCE g_hInst; extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: g_hInst = hInstance; dll_process_attach( hInstance, true ); break; case DLL_PROCESS_DETACH: dll_process_detach( hInstance, true ); break; case DLL_THREAD_ATTACH: dll_thread_attach( true, true ); break; case DLL_THREAD_DETACH: dll_thread_detach( true, true ); break; } return true; } Then as soon as your DLL is loaded the D runtime will start. Any memory allocated in the D DLL will be garbage collected as you'd imagine. Obviously, it's not going to free any memory allocated in your C++ code ;)
Jul 17 2011
parent reply Loopback <elliott.darfink gmail.com> writes:
On 2011-07-17 22:51, Johann MacDonagh wrote:
 On 7/17/2011 3:53 PM, Loopback wrote:
 On 2011-07-17 21:45, Loopback wrote:
 Hello!

 As of my understanding you can write usable c libraries in D by using
 extern(C). The problem is that I haven't found any other threads asking
 the same question about C++ (since extern for c++ exists as well). So
 I have two questions, is it possible to write a dll in D usable in c++
 code, and if the answer is yes, are there any restrictions?

 Am I forced to use explicit memory handling, or can this be handled by
 the garbage collection internally by the dll etc?
Sorry for mentioning this a bit late but noticed this now; http://www.digitalmars.com/d/2.0/cpp_interface.html Although if someone has own experiences or something interesting to say about the matter, please do.
I think you're going to be better off defining your D routines as extern(C) and then defining the C++ headers as __cdecl (for Windows of course). C++ can, of course, link against libraries using cdecl. If you write your D DLL with the normal DllEntry (this came from VisualD): import std.c.windows.windows; import core.dll_helper; __gshared HINSTANCE g_hInst; extern (Windows) BOOL DllMain(HINSTANCE hInstance, ULONG ulReason, LPVOID pvReserved) { switch (ulReason) { case DLL_PROCESS_ATTACH: g_hInst = hInstance; dll_process_attach( hInstance, true ); break; case DLL_PROCESS_DETACH: dll_process_detach( hInstance, true ); break; case DLL_THREAD_ATTACH: dll_thread_attach( true, true ); break; case DLL_THREAD_DETACH: dll_thread_detach( true, true ); break; } return true; } Then as soon as your DLL is loaded the D runtime will start. Any memory allocated in the D DLL will be garbage collected as you'd imagine. Obviously, it's not going to free any memory allocated in your C++ code ;)
Thank you for your reply! I've written a C++ wrapper which communicates with D function but I have stumbled upon an error. With the code win32 DLL code on the digitalmars webpage (and yours) I receive linker errors: Error 42: Symbol Undefined _D4core10dll_helper18dll_process_detachFT4core3sys7w indows7windows6HANDLEbZv Error 42: Symbol Undefined _D4core10dll_helper18dll_process_attachFT4core3sys7w indows7windows6HANDLEbPvPvPvPiZb Error 42: Symbol Undefined _D4core13thread_helper12__ModuleInfoZ From my experience ModuleInfo undefined is often caused by not supplying a required source file to the linker, but since I only use functions from the library, I shouldn't be required to do that. Any tips?
Jul 18 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
import core.dll_helper; is outdated, use import core.sys.windows.dll;
And also import core.runtime;
Jul 18 2011
parent reply Loopback <elliott.darfink gmail.com> writes:
On 2011-07-18 21:59, Andrej Mitrovic wrote:
 import core.dll_helper; is outdated, use import core.sys.windows.dll;
 And also import core.runtime;
Are there any examples covering these new modules, or are the procedure the same?
Jul 18 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/18/11, Loopback <elliott.darfink gmail.com> wrote:
 On 2011-07-18 21:59, Andrej Mitrovic wrote:
 import core.dll_helper; is outdated, use import core.sys.windows.dll;
 And also import core.runtime;
Are there any examples covering these new modules, or are the procedure the same?
It's all pretty much the same as the page says. There's a DLL example in this folder: \DMD\dmd2\samples\d\mydll
Jul 18 2011
parent reply Johann MacDonagh <johann.macdonagh.no spam.gmail.com> writes:
On 7/18/2011 5:04 PM, Andrej Mitrovic wrote:
 On 7/18/11, Loopback<elliott.darfink gmail.com>  wrote:
 On 2011-07-18 21:59, Andrej Mitrovic wrote:
 import core.dll_helper; is outdated, use import core.sys.windows.dll;
 And also import core.runtime;
Are there any examples covering these new modules, or are the procedure the same?
It's all pretty much the same as the page says. There's a DLL example in this folder: \DMD\dmd2\samples\d\mydll
Looks like VisualD's DLL template needs to be updated. FWIW I was able to compile and link a D DLL with the code I copy pasted in the other message. Loopback, do you have Visual Studio on your dev box? If so you should take a look at VisualD: http://www.dsource.org/projects/visuald Let us know if you're not able to compile a D DLL.
Jul 18 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/19/11, Johann MacDonagh <johann.macdonagh.no spam.gmail.com> wrote:
 FWIW I was able to compile and link a D DLL with the code I copy pasted
 in the other message.
Maybe you're running 2.052. I think in 2.053 dll_helper disappeared, and so in 2.054: D:\dev\code\d_code\DLLTest>dmd mydll.d mydll.d(9): Error: module dll_helper is in file 'core\dll_helper.d' which cannot be read
Jul 18 2011
parent Johann MacDonagh <johann.macdonagh.no spam.gmail.com> writes:
On 7/18/2011 7:08 PM, Andrej Mitrovic wrote:
 On 7/19/11, Johann MacDonagh<johann.macdonagh.no spam.gmail.com>  wrote:
 FWIW I was able to compile and link a D DLL with the code I copy pasted
 in the other message.
Maybe you're running 2.052. I think in 2.053 dll_helper disappeared, and so in 2.054: D:\dev\code\d_code\DLLTest>dmd mydll.d mydll.d(9): Error: module dll_helper is in file 'core\dll_helper.d' which cannot be read
Oh wow, you're correct. I was missing with dvm and had an old version ;)
Jul 18 2011
prev sibling parent reply Loopback <elliott.darfink gmail.com> writes:
On 2011-07-19 00:56, Johann MacDonagh wrote:
 On 7/18/2011 5:04 PM, Andrej Mitrovic wrote:
 On 7/18/11, Loopback<elliott.darfink gmail.com> wrote:
 On 2011-07-18 21:59, Andrej Mitrovic wrote:
 import core.dll_helper; is outdated, use import core.sys.windows.dll;
 And also import core.runtime;
Are there any examples covering these new modules, or are the procedure the same?
It's all pretty much the same as the page says. There's a DLL example in this folder: \DMD\dmd2\samples\d\mydll
Looks like VisualD's DLL template needs to be updated. FWIW I was able to compile and link a D DLL with the code I copy pasted in the other message. Loopback, do you have Visual Studio on your dev box? If so you should take a look at VisualD: http://www.dsource.org/projects/visuald Let us know if you're not able to compile a D DLL.
Thanks for all of your replies! It seems as if the problem was solved by using core.sys.windows.dll instead. Although I do have a bit of a problem. As I mentioned earlier I wanted to make a DLL which C++ applications could interface with. By making this possible, I have a "dll.d" file (just as the example) and a "mydll.d" file - the file which implements the dll functions. In this file, I have declared a function like this (testing purpose): extern(C++) void SetInt(int * foo) { *foo = 5; } When I compile this program with this DMD command line: dmd -ofmydll.dll -L/IMPLIB mydll.d dll.d mydll.def I get a successful compile, and a DLL file generated. For some reason, I also get a ATA.lib file, which is exactly 1.00 KB big (any ideas why)? The problem though, is related to the C++ side. I load the DLL dynamically using "LoadLibraryA" function, and then I try to load the SetInt function using GetProcAddress. The LoadLibrary function succeeds but the GetProcAddress function call fails saying that the function could not be found. typedef void (*PFGMO)(int*); void main(int argc, char ** argv) { // Function Pointer PFGMO pFGMO = NULL; HINSTANCE library; if((library = LoadLibraryA("C:\\mydll.dll")) == NULL) throw 1; bool result = (pFGMO = (PFGMO) GetProcAddress(library, "SetInt")) != NULL; // Result is zero (failed) std::cout << "Result: " << result; std::cin.get(); } How come the procedure address cannot be found and how to solve it? If of interest, this is the .def file (mydll.def) LIBRARY "mydll.dll" EXETYPE NT SUBSYSTEM WINDOWS CODE SHARED EXECUTE DATA WRITE When viewing the DLL with PE Explorer (program to explore executable files) it reports that the number of symbols are zero. Is this related to the problem perhaps?
Jul 18 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
You have several problems.

extern(C++) only specifies the calling convention, not the visibility
of the symbol. To export the symbol, list it in a .def file or mark
the function with export in the module itself, ala:

export extern(C++) void SetInt(int * foo) {}

I don't know why, but if you use a .def file instead of `export` the
function will be exported as a C function with no name mangling.

Anyway, use a .def file like the one below and pass it to DMD while
compiling the DLL, and it should be exported with that name (and
change the string "mydll.dll" of course):

LIBRARY         "mydll.dll"
DESCRIPTION     'My DLL written in D'
EXETYPE		    NT
SUBSYSTEM       WINDOWS
CODE            PRELOAD DISCARDABLE
DATA            WRITE

EXPORTS
    SetInt


ATA.lib is probably the autogenerated import library which is useful
for implicit linking.
Jul 18 2011
next sibling parent reply Johann MacDonagh <johann.macdonagh.no spam.gmail.com> writes:
On 7/18/2011 10:40 PM, Andrej Mitrovic wrote:
 You have several problems.

 extern(C++) only specifies the calling convention, not the visibility
 of the symbol. To export the symbol, list it in a .def file or mark
 the function with export in the module itself, ala:

 export extern(C++) void SetInt(int * foo) {}
If you export it like this, it will be exported as the C++ mangled name. If you have extern(C) it will be cdecl "_SetInt" and extern(Windows) will be stdcall "_SetInt 4".
 I don't know why, but if you use a .def file instead of `export` the
 function will be exported as a C function with no name mangling.
If you look at dumpbin /exports you'll see something like this: ordinal hint RVA name 1 0 0000306C SetInt = ?SetInt YAXPAH Z (void __cdecl SetInt(int *)) So the symbol still has C++ name mangling but its exported as whatever name you want.
Jul 18 2011
next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 7/19/11, Johann MacDonagh <johann.macdonagh.no spam.gmail.com> wrote:
 If you export it like this, it will be exported as the C++ mangled name.
 If you have extern(C) it will be cdecl "_SetInt" and extern(Windows)
 will be stdcall "_SetInt 4".
Right, that's all pretty standard stuff. :)
 I don't know why, but if you use a .def file instead of `export` the
 function will be exported as a C function with no name mangling.
If you look at dumpbin /exports you'll see something like this: ordinal hint RVA name 1 0 0000306C SetInt = ?SetInt YAXPAH Z (void __cdecl SetInt(int *)) So the symbol still has C++ name mangling but its exported as whatever name you want.
See I tried using dumpbin, but apparently I wiped it from my PATH so I had to rely on DLL Export viewer (because I'm lazy and it had an icon on my desktop!) which doesn't even show this. I had a hunch that was happening behind the scenes. Thanks for the info regardless hehe.
Jul 18 2011
parent Johann MacDonagh <johann.macdonagh.no spam.gmail.com> writes:
On 7/18/2011 11:52 PM, Andrej Mitrovic wrote:
 See I tried using dumpbin, but apparently I wiped it from my PATH so I
 had to rely on DLL Export viewer (because I'm lazy and it had an icon
 on my desktop!) which doesn't even show this. I had a hunch that was
 happening behind the scenes. Thanks for the info regardless hehe.
If you open a Visual Studio Command Prompt it should be in your PATH. Also, you won't see the internal symbol name unless you have pdb symbols in the same directory as the DLL (VisualD converts the symbols for me, which is why I saw it).
Jul 18 2011
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Uhh, I tried using ASM to simulate the thiscall calling convention, it
didn't go all to well. :) A wrapper C++ DLL that exposes a C interface
was my workaround.

Here's a page that talks about some problems with passing objects via DLLs:
http://www.prowiki.org/wiki4d/wiki.cgi?BestPractices/DLL
Jul 18 2011
prev sibling parent reply Loopback <elliott.darfink gmail.com> writes:
On 2011-07-19 04:40, Andrej Mitrovic wrote:
 You have several problems.

 extern(C++) only specifies the calling convention, not the visibility
 of the symbol. To export the symbol, list it in a .def file or mark
 the function with export in the module itself, ala:

 export extern(C++) void SetInt(int * foo) {}

 I don't know why, but if you use a .def file instead of `export` the
 function will be exported as a C function with no name mangling.

 Anyway, use a .def file like the one below and pass it to DMD while
 compiling the DLL, and it should be exported with that name (and
 change the string "mydll.dll" of course):

 LIBRARY         "mydll.dll"
 DESCRIPTION     'My DLL written in D'
 EXETYPE		    NT
 SUBSYSTEM       WINDOWS
 CODE            PRELOAD DISCARDABLE
 DATA            WRITE

 EXPORTS
      SetInt


 ATA.lib is probably the autogenerated import library which is useful
 for implicit linking.
Seems as if this fixed it, thank you! I want to ask though how I am supposed to go about to enable class communication. For example; if I define a interface, and inherit this interface in a class, C++ can use these class functions by defining a analogous class (instead of interface) with virtual functions. If I create a class dynamically on the heap (in my dll), and then make a function that c++ can call to receive this object, how should I proceed then? extern(C++) interface Base { int Test(); } class Foo : Base { public: extern(C++) int Test() { return 5; } } export extern(C++) void GetObject(Base base) { Foo temp = new Foo; base = Foo; } This is just a example to explain what I want to accomplish. One problem with this code, is that a memory exception is thrown on the C++ side if this function is called, whenever I use the "new" operator. Is this because it's a export/extern function? // C++ Code class Base { public: virtual int Test(void); }; What is the best method to accomplish this, and are there any limitations with this method (do I have to allocate the class with malloc instead etc.)?
Jul 18 2011
parent reply Johann MacDonagh <johann.macdonagh.no spam.gmail.com> writes:
On 7/18/2011 11:27 PM, Loopback wrote:
 On 2011-07-19 04:40, Andrej Mitrovic wrote:
 You have several problems.

 extern(C++) only specifies the calling convention, not the visibility
 of the symbol. To export the symbol, list it in a .def file or mark
 the function with export in the module itself, ala:

 export extern(C++) void SetInt(int * foo) {}

 I don't know why, but if you use a .def file instead of `export` the
 function will be exported as a C function with no name mangling.

 Anyway, use a .def file like the one below and pass it to DMD while
 compiling the DLL, and it should be exported with that name (and
 change the string "mydll.dll" of course):

 LIBRARY "mydll.dll"
 DESCRIPTION 'My DLL written in D'
 EXETYPE NT
 SUBSYSTEM WINDOWS
 CODE PRELOAD DISCARDABLE
 DATA WRITE

 EXPORTS
 SetInt


 ATA.lib is probably the autogenerated import library which is useful
 for implicit linking.
Seems as if this fixed it, thank you! I want to ask though how I am supposed to go about to enable class communication. For example; if I define a interface, and inherit this interface in a class, C++ can use these class functions by defining a analogous class (instead of interface) with virtual functions. If I create a class dynamically on the heap (in my dll), and then make a function that c++ can call to receive this object, how should I proceed then? extern(C++) interface Base { int Test(); } class Foo : Base { public: extern(C++) int Test() { return 5; } } export extern(C++) void GetObject(Base base) { Foo temp = new Foo; base = Foo; } This is just a example to explain what I want to accomplish. One problem with this code, is that a memory exception is thrown on the C++ side if this function is called, whenever I use the "new" operator. Is this because it's a export/extern function? // C++ Code class Base { public: virtual int Test(void); }; What is the best method to accomplish this, and are there any limitations with this method (do I have to allocate the class with malloc instead etc.)?
Your C++ class "Base" is not compatible with your D "Foo" class. The v-tables are not guaranteed to be identical. I'm not even sure if D's thiscall is the same as C++'s thiscall. It's just not going to work. Most languages don't support this. This is why we use C bindings. Everyone supports C ;) Now, you can do something like this: struct Foo { int x; float y; } extern(C) void* GetNewFoo() { // Note: Don't use new here otherwise the GC may clean it up return cast(void*) core.memory.GC.malloc(Foo.sizeof); } extern(C) float Foo_DoSomething(Foo* foo) { return foo.x + foo.y; } extern(C) void FreeFoo(Foo* foo) { core.memory.GC.free(foo); } I haven't tried this, but something like this should work. Structs are inherently compatible between languages. Of course, you won't be able to do any kind of polymorphism. Does this help?
Jul 18 2011
parent reply Loopback <elliott.darfink gmail.com> writes:
On 2011-07-19 05:46, Johann MacDonagh wrote:
 What is the best method to accomplish this, and are there any
 limitations with this method (do I have to allocate the class with
 malloc instead etc.)?
Your C++ class "Base" is not compatible with your D "Foo" class. The v-tables are not guaranteed to be identical. I'm not even sure if D's thiscall is the same as C++'s thiscall. It's just not going to work. Most languages don't support this. This is why we use C bindings. Everyone supports C ;) Now, you can do something like this: struct Foo { int x; float y; } extern(C) void* GetNewFoo() { // Note: Don't use new here otherwise the GC may clean it up return cast(void*) core.memory.GC.malloc(Foo.sizeof); } extern(C) float Foo_DoSomething(Foo* foo) { return foo.x + foo.y; } extern(C) void FreeFoo(Foo* foo) { core.memory.GC.free(foo); } I haven't tried this, but something like this should work. Structs are inherently compatible between languages. Of course, you won't be able to do any kind of polymorphism. Does this help?
Very interesting! This might help depends; are you able to have structures with functions? Are they still analogous if you implement them? Also, how come the class-interface inheritance didn't work to communicate with C++. Is the "Interface to C++" doc's outdated? "Calling D Virtual Functions From C++" http://www.digitalmars.com/d/2.0/cpp_interface.html
Jul 19 2011
parent Loopback <elliott.darfink gmail.com> writes:
On 2011-07-19 12:39, Loopback wrote:
 On 2011-07-19 05:46, Johann MacDonagh wrote:
 What is the best method to accomplish this, and are there any
 limitations with this method (do I have to allocate the class with
 malloc instead etc.)?
Your C++ class "Base" is not compatible with your D "Foo" class. The v-tables are not guaranteed to be identical. I'm not even sure if D's thiscall is the same as C++'s thiscall. It's just not going to work. Most languages don't support this. This is why we use C bindings. Everyone supports C ;) Now, you can do something like this: struct Foo { int x; float y; } extern(C) void* GetNewFoo() { // Note: Don't use new here otherwise the GC may clean it up return cast(void*) core.memory.GC.malloc(Foo.sizeof); } extern(C) float Foo_DoSomething(Foo* foo) { return foo.x + foo.y; } extern(C) void FreeFoo(Foo* foo) { core.memory.GC.free(foo); } I haven't tried this, but something like this should work. Structs are inherently compatible between languages. Of course, you won't be able to do any kind of polymorphism. Does this help?
Very interesting! This might help depends; are you able to have structures with functions? Are they still analogous if you implement them? Also, how come the class-interface inheritance didn't work to communicate with C++. Is the "Interface to C++" doc's outdated? "Calling D Virtual Functions From C++" http://www.digitalmars.com/d/2.0/cpp_interface.html
I noticed that function seems to work functions with structures. Are there any restrictions worth knowing or is it just like any other structure when D and C++ communicate? Can I have private variables, public, properties etc? And just not to forget, why the C++ and interface class didn't work?
Jul 19 2011