www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - State of interfacing with c++

reply Jonas Drewsen <nospam4321 hotmail.com> writes:
For a hack week at work I am thinking about creating a module in 
D that can be used with our existing application which is written 
in C++.

Can anyone shed some light on the current status of interfacing 
with C++? In particular:

1, Can I build my C++ program using visual c++ and then link a D 
module compiled with gdc/ldc/dmd into it using the ms linker?

2, Can I do the same with the OSX tool chain ie. compile main 
program using xcode clang etc.

3, And what about linux?

3, Which features of D or C++ should I expect not to work or 
shouldn't use when interfacing.

Any pointers to reasonably up-to-date info about interfacing with 
c++ is much appreciated as well.

Thanks
Mar 18 2016
next sibling parent reply Johan Engelen <j j.nl> writes:
On Friday, 18 March 2016 at 13:45:18 UTC, Jonas Drewsen wrote:
 For a hack week at work I am thinking about creating a module 
 in D that can be used with our existing application which is 
 written in C++.

 Can anyone shed some light on the current status of interfacing 
 with C++? In particular:

 1, Can I build my C++ program using visual c++ and then link a 
 D module compiled with gdc/ldc/dmd into it using the ms linker?
This is what we do for LDC. Perhaps the only annoyance is that you have to know what linker flags gdc/ldc/dmd use. See https://github.com/ldc-developers/ldc/blob/master/CMakeLists.txt#L126-L177 It'd be nice to be able to call `dmd -ldflags` whose output would be the standard linker flags.
 3, Which features of D or C++ should I expect not to work or 
 shouldn't use when interfacing.
C++ constructors/destructors are different from their D siblings. To help with this, you can define creation/destruction helper functions that you would call from the other domain, for example C++ calling a "Class* createClass(...)" function, defined in D as something like extern(C++) Class createClass(...) { return new Class(...); }
Mar 18 2016
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/18/2016 6:59 AM, Johan Engelen wrote:
 It'd be nice to be able to call `dmd -ldflags` whose output would be the
 standard linker flags.
dmd -v file.d will tell you what command is sent to the linker.
Mar 18 2016
parent reply Johan Engelen <j j.nl> writes:
On Friday, 18 March 2016 at 20:47:41 UTC, Walter Bright wrote:
 On 3/18/2016 6:59 AM, Johan Engelen wrote:
 It'd be nice to be able to call `dmd -ldflags` whose output 
 would be the
 standard linker flags.
dmd -v file.d will tell you what command is sent to the linker.
That linker command does not include the path to phobos. You would have to parse the output, etc...
Mar 19 2016
parent reply Johan Engelen <j j.nl> writes:
On Saturday, 19 March 2016 at 08:10:41 UTC, Johan Engelen wrote:
 On Friday, 18 March 2016 at 20:47:41 UTC, Walter Bright wrote:
 On 3/18/2016 6:59 AM, Johan Engelen wrote:
 It'd be nice to be able to call `dmd -ldflags` whose output 
 would be the
 standard linker flags.
dmd -v file.d will tell you what command is sent to the linker.
That linker command does not include the path to phobos. You would have to parse the output, etc...
Would you accept a PR that adds `dmd -ldflags` ? For C++/D linking, I used the C++ linker for LDC (master), but now I am changing it to using the D compiler with "-L-lstdc++" to link. It solves the issue of finding the location of phobos/druntime (different for dmd and ldc) and other required libs for D code. It also solves a Windows-specific linking problem when main() is in C++ code [1]. [1] http://forum.dlang.org/post/livbjrlaoliqjtmmwnht forum.dlang.org
Mar 19 2016
parent Johan Engelen <j j.nl> writes:
On Saturday, 19 March 2016 at 10:52:35 UTC, Johan Engelen wrote:
 On Saturday, 19 March 2016 at 08:10:41 UTC, Johan Engelen wrote:
 On Friday, 18 March 2016 at 20:47:41 UTC, Walter Bright wrote:
 On 3/18/2016 6:59 AM, Johan Engelen wrote:
 It'd be nice to be able to call `dmd -ldflags` whose output 
 would be the
 standard linker flags.
dmd -v file.d will tell you what command is sent to the linker.
That linker command does not include the path to phobos. You would have to parse the output, etc...
Would you accept a PR that adds `dmd -ldflags` ? For C++/D linking, I used the C++ linker for LDC (master), but now I am changing it to using the D compiler with "-L-lstdc++" to link. It solves the issue of finding the location of phobos/druntime (different for dmd and ldc) and other required libs for D code. It also solves a Windows-specific linking problem when main() is in C++ code [1].
Unfortunately, this was not true. If your D code does not have main(), linking does no work with DMD on Windows: phobos is not linked when there is no main(). Note that "phobos" also contains druntime and so a D source file with only "void foo() {}" does not link, and results in unresolved external symbol _d_assert among others. This is giving me a major headache at the moment while trying to change LDC's build. (on Linux and Mac, it turns out things are easier)
Mar 19 2016
prev sibling next sibling parent reply Jakob Ovrum <jakobovrum gmail.com> writes:
On Friday, 18 March 2016 at 13:45:18 UTC, Jonas Drewsen wrote:
 Any pointers to reasonably up-to-date info about interfacing 
 with c++ is much appreciated as well.
The language documentation is up to date except for the section on exceptions: http://dlang.org/spec/cpp_interface.html I'd update the section on exceptions but I'm really tired of fighting the dlang.org makefile. http://forum.dlang.org/post/aupwqmkicdjzwxdkklnt forum.dlang.org
Mar 18 2016
parent tsbockman <thomas.bockman gmail.com> writes:
On Friday, 18 March 2016 at 14:11:46 UTC, Jakob Ovrum wrote:
 I'd update the section on exceptions but I'm really tired of 
 fighting the dlang.org makefile.

 http://forum.dlang.org/post/aupwqmkicdjzwxdkklnt forum.dlang.org
If you'll write an update for the C++ exceptions section as plain text, I'll do the DDoc markup, fight with the makefile, and make a pull request for you. (I would need you to be available to answer content-related questions on the pull request, though.)
Mar 18 2016
prev sibling next sibling parent reply ZombineDev <petar.p.kirov gmail.com> writes:
On Friday, 18 March 2016 at 13:45:18 UTC, Jonas Drewsen wrote:
 For a hack week at work I am thinking about creating a module 
 in D that can be used with our existing application which is 
 written in C++.

 Can anyone shed some light on the current status of interfacing 
 with C++? In particular:

 1, Can I build my C++ program using visual c++ and then link a 
 D module compiled with gdc/ldc/dmd into it using the ms linker?

 2, Can I do the same with the OSX tool chain ie. compile main 
 program using xcode clang etc.

 3, And what about linux?

 3, Which features of D or C++ should I expect not to work or 
 shouldn't use when interfacing.

 Any pointers to reasonably up-to-date info about interfacing 
 with c++ is much appreciated as well.

 Thanks
If you need only static linking, 1, 2 and 3 should all work fine with DMD, if you call into the D module through extern(C) functions. If you want use C++ interface it's a little more complicated - see http://dlang.org/spec/cpp_interface.html, which was updated recently. The important thing to remember is that the Druntime must be initialized (see http://wiki.dlang.org/Runtime_internals and http://dlang.org/phobos/core_runtime.html#.rt_init for more info), before you call D functions that use the garbage collector. If all your D code is nogc nothrow, you shouldn't need to do any initialization. AFAIK, GDC doesn't support Windows and is on par with DMD 2.067. LDC recently got a lot of momentum - the LDC master branch is on par with DMD 2.069.2 which means it uses the DMD frontend which is written in D, while being a C++ application which uses the C++ LLVM interface. It's quite an accomplishment because it would make LDC 1.0.0 the largest mixed C++ and D application compiled with LDC. There's been also a lot of work on the MSVC front lately.
Mar 18 2016
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Friday, 18 March 2016 at 14:26:31 UTC, ZombineDev wrote:
 The important thing to remember is that the Druntime must be 
 initialized (see http://wiki.dlang.org/Runtime_internals and 
 http://dlang.org/phobos/core_runtime.html#.rt_init for more 
 info), before you call D functions that use the garbage 
 collector. If all your D code is  nogc nothrow, you shouldn't 
 need to do any initialization.
You mean if you call D functions in C++, you have to use rt_init to enable the garbage collector. I don't see that mentioned on the Interfacing to C++ page. Probably worth adding. Other suggestions: 1) Split up the C++ templates section of that page, instead of just being big blocks of code. 2) In the memory allocation section, it mentions for ways to ensure D garbage is collected properly by C++. Might provide a simple example of each technique.
Mar 18 2016
parent reply ZombineDev <petar.p.kirov gmail.com> writes:
On Friday, 18 March 2016 at 15:29:55 UTC, jmh530 wrote:
 On Friday, 18 March 2016 at 14:26:31 UTC, ZombineDev wrote:
 The important thing to remember is that the Druntime must be 
 initialized (see http://wiki.dlang.org/Runtime_internals and 
 http://dlang.org/phobos/core_runtime.html#.rt_init for more 
 info), before you call D functions that use the garbage 
 collector. If all your D code is  nogc nothrow, you shouldn't 
 need to do any initialization.
You mean if you call D functions in C++, you have to use rt_init to enable the garbage collector.
I'm sorry, what I said about rt_init() [1] is wrong. It does a lot of stuff and it's not just enabling the garbage collector. This means you have to be more careful if you decide to not call it. Here's what it does: 1. Initializes the global mutex that guards the creation of per object monitors, needed for the synchronized (obj) statement. 2. Initializes the first mutex in the critical section linked list, needed for the synchronized {} statement. 3. Locates the sections from the binary where the module info & module ctor / dtors are located 4. Queries the OS about the clock resolution needed in order for MonoTime to be usable. 5. Initializes the internal structures of the GC and reserves some initial amount of memory as per the GC config. 6. Adds the static data and bss segments to the GC ranges, so they can be scanned. 7. Initializes the callStructDtorsDuringGC flag by reading the GC config. 8. Runs shared module ctors 9. Run non-shared module ctors [1]: https://github.com/D-Programming-Language/druntime/blob/master/src/rt/dmain2.d#L158
 I don't see that mentioned on the Interfacing to C++ page. 
 Probably worth adding.

 Other suggestions:
 1) Split up the C++ templates section of that page, instead of 
 just being big blocks of code.
 2) In the memory allocation section, it mentions for ways to 
 ensure D garbage is collected properly by C++. Might provide a 
 simple example of each technique.
I agree.
Mar 18 2016
parent jmh530 <john.michael.hall gmail.com> writes:
On Friday, 18 March 2016 at 19:21:08 UTC, ZombineDev wrote:
 I'm sorry, what I said about rt_init() [1] is wrong. It does a 
 lot of stuff and it's not just enabling the garbage collector. 
 This means you have to be more careful if you decide to not 
 call it. Here's what it does:
If it is useful when calling D code from C/C++, then it should be mentioned somewhere. And the fact that you've already looked in to what it does puts you in a good position to write a summary!
Mar 18 2016
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 3/18/2016 6:45 AM, Jonas Drewsen wrote:
 [...]
dmd itself is a D main program that calls a lot of C++ code (the optimizer and back end) and so interfacing to C++ works on every platform dmd runs on.
Mar 18 2016
parent Jonas Drewsen <nospam4321 hotmail.com> writes:
On Friday, 18 March 2016 at 20:50:59 UTC, Walter Bright wrote:
 On 3/18/2016 6:45 AM, Jonas Drewsen wrote:
 [...]
dmd itself is a D main program that calls a lot of C++ code (the optimizer and back end) and so interfacing to C++ works on every platform dmd runs on.
My concern was mostly if I could use visual c++ compiled backed to link with dmd/ldc/gdc compiled modules or if the c++ part must to be compiled a non-vc compiler e.g. dmc, gcc, clang to work. Because making our existing app compile on e.g. windows using something else that visual c++ would definitely increase the work load.
Mar 19 2016