www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Linking C++ with a D-library

reply "Milvakili" <maliy.kayit gmail.com> writes:
Hi, I'm a new to D and I could not find any relevant answers in 
the forum.

I want to call functions from D-lib from c++ main.
dlibrary

import std.stdio;

extern (C++) void foo(int i, int j, int k) {
   writefln("i = %s", i);
   writefln("j = %s", j);
   writefln("k = %s", k);
}
void main(){}


c++ binary

#include <iostream>

void CXXmain();
void foo(int i, int j, int k);
using namespace std;

int main(){
   cout << "This is the main of C++\n";
   foo(1,3,4);
   return 0;
}


I can compile d with dmd and c++ with g++ then linked them with 
g++.  The problem is when I run the binary I got:

 ./runtest
This is the main of C++ Segmentation Fault I could not figure out the problem. And when I call the C++ functions from the main of D everything works. So why have I segmentation when I call the main from C++.
Jun 26 2013
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
On Wednesday, 26 June 2013 at 20:19:07 UTC, Milvakili wrote:
 Hi, I'm a new to D and I could not find any relevant answers in 
 the forum.

 I want to call functions from D-lib from c++ main.
 dlibrary

 import std.stdio;

 extern (C++) void foo(int i, int j, int k) {
   writefln("i = %s", i);
   writefln("j = %s", j);
   writefln("k = %s", k);
 }
 void main(){}
Try adding this to D: extern(C) void initialize_D() { import core.runtime; Runtime.initialize(); } And this to C++:
 void foo(int i, int j, int k);
extern "C" void initialize_d();
 using namespace std;

 int main(){
initialize_d();
   cout << "This is the main of C++\n";
   foo(1,3,4);
   return 0;
 }
And you should see something better.
Jun 26 2013
parent reply "Milvakili" <maliy.kayit gmail.com> writes:
On Wednesday, 26 June 2013 at 20:23:35 UTC, Adam D. Ruppe wrote:
 On Wednesday, 26 June 2013 at 20:19:07 UTC, Milvakili wrote:
 Hi, I'm a new to D and I could not find any relevant answers 
 in the forum.

 I want to call functions from D-lib from c++ main.
 dlibrary

 import std.stdio;

 extern (C++) void foo(int i, int j, int k) {
  writefln("i = %s", i);
  writefln("j = %s", j);
  writefln("k = %s", k);
 }
 void main(){}
Try adding this to D: extern(C) void initialize_D() { import core.runtime; Runtime.initialize(); } And this to C++:
 void foo(int i, int j, int k);
extern "C" void initialize_d();
 using namespace std;

 int main(){
initialize_d();
  cout << "This is the main of C++\n";
  foo(1,3,4);
  return 0;
 }
And you should see something better.
That "magically" solves my problem. Would you mind if I ask you to define what this initialization is all about or guide me to some tutorial related to these issues? Thanks alot.
Jun 26 2013
parent reply Justin Whear <justin economicmodeling.com> writes:
On Wed, 26 Jun 2013 22:32:55 +0200, Milvakili wrote: 
 That "magically" solves my problem.  Would you mind if I ask you to
 define what this initialization is all about or guide me to some
 tutorial related to these issues?
 
 Thanks alot.
The function initializes the D runtime library. I believe the initialization must be done primarily due to the garbage collector, but there's a list of what the runtime provides in the readme here: https:// github.com/D-Programming-Language/druntime
Jun 26 2013
parent reply "Milvakili" <maliy.kayit gmail.com> writes:
On Wednesday, 26 June 2013 at 20:37:25 UTC, Justin Whear wrote:
 On Wed, 26 Jun 2013 22:32:55 +0200, Milvakili wrote:
 That "magically" solves my problem.  Would you mind if I ask 
 you to
 define what this initialization is all about or guide me to 
 some
 tutorial related to these issues?
 
 Thanks alot.
The function initializes the D runtime library. I believe the initialization must be done primarily due to the garbage collector, but there's a list of what the runtime provides in the readme here: https:// github.com/D-Programming-Language/druntime
Great!
Jun 26 2013
parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
I think specifically for writefln it needs to grab module 
constructors from the initialization, to set up the output 
stream. The GC and typeinfo would be important for a longer 
example.

You might also want to do something similar at the end of C++'s 
main with Runtime.terminate().
Jun 26 2013
parent reply "Milvakili" <maliy.kayit gmail.com> writes:
On Wednesday, 26 June 2013 at 21:12:26 UTC, Adam D. Ruppe wrote:
 I think specifically for writefln it needs to grab module 
 constructors from the initialization, to set up the output 
 stream. The GC and typeinfo would be important for a longer 
 example.

 You might also want to do something similar at the end of C++'s 
 main with Runtime.terminate().
Thanks. What about the other way around. If I linked them with dmd in that case it throws errors due to <iostream>, what should I do in that case?
Jun 26 2013
parent "Adam D. Ruppe" <destructionator gmail.com> writes:
On Thursday, 27 June 2013 at 00:00:23 UTC, Milvakili wrote:
 What about the other way around. If I linked them with dmd in 
 that case it throws errors due to <iostream>, what should I do 
 in that case?
I don't think you need to do any special C++ initialization, any needed work there is automatically inserted by the linker. Just make sure you link with -L-lstdc++ if you're linking with dmd on Linux and the needed c++ lib should be pulled in. Or if you want to link with g++ or ld, you'll want to link in -lphobos2 to get the D standard library. Running dmd -v can be helpful to see exactly what is going on: $ dmd -v test.d < snip a lot of stuff > gcc test25.o -o test25 -m32 -L/home/me/d/dmd2/linux/bin32/../lib32 -L/home/me/d/dmd2/linux/bin32/../lib64 -Xlinker --no-warn-search-mismatch -Xlinker --export-dynamic -l:libphobos2.a -lpthread -lm -lrt $ Right at the end, you can see the command dmd is running to do the link. It uses gcc here, passing a bunch of libraries D will need. But if you just let dmd do the link you can add C++ libraries with -L-l.
Jun 26 2013