www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Re: Writing a library

reply Mn <mn mailinator.com> writes:
Jarrett Billingsley Wrote:

 "Mn" <mn mailinator.com> wrote in message 
 news:er492f$1sti$1 digitalmars.com...
 Hello World!

 Is it possible to write a library in D that can be used by other 
 programming languages? And if yes, how to do it? I can think of two ways 
 of "using" a lib in general:

 1. The OOP way: use a class of the lib, then its functions, dunno how its 
 called.
 2. The Un-OOP way: use a function of a lib, its called P/Invoke in C#.

 I am only interested in the more popular languages like C, C++, Java, C#, 
 PHP.

 Greetings and thank you.
 -- Mn

No other languages understand D calling or mangling conventions, but D can make functions with C, Windows, and Pascal calling conventions. If you just do something like: extern(C) export void func(int x) { ... } You can then, maybe, make a DLL or something out of it which can be called from virtually any other mainstream language, since most things understand the C calling convention.

So if I want to create an instance of a class, the instance being created outside but the class being inside the lib, and then the class staying alive until I somehow get rid of it (calling a function of the class) - is this possible? Short: is it possible to export a class, not only its functions? If yes, how? Thanks. -- Mn
Feb 16 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Mn wrote:
 Jarrett Billingsley Wrote:
 
 "Mn" <mn mailinator.com> wrote in message 
 news:er492f$1sti$1 digitalmars.com...
 Hello World!

 Is it possible to write a library in D that can be used by other 
 programming languages? And if yes, how to do it? I can think of two ways 
 of "using" a lib in general:

 1. The OOP way: use a class of the lib, then its functions, dunno how its 
 called.
 2. The Un-OOP way: use a function of a lib, its called P/Invoke in C#.

 I am only interested in the more popular languages like C, C++, Java, C#, 
 PHP.

 Greetings and thank you.
 -- Mn

make functions with C, Windows, and Pascal calling conventions. If you just do something like: extern(C) export void func(int x) { ... } You can then, maybe, make a DLL or something out of it which can be called from virtually any other mainstream language, since most things understand the C calling convention.

So if I want to create an instance of a class, the instance being created outside but the class being inside the lib, and then the class staying alive until I somehow get rid of it (calling a function of the class) - is this possible? Short: is it possible to export a class, not only its functions? If yes, how? Thanks. -- Mn

I think what you need to do is basically to mimic the type of interface used by C FILE operations, if you are familiar with that. So you will need a create() call that returns a MY_CLASS, which is actually just a void pointer. In fact it will be a pointer to your class object, but from C land all they will know is that it's a void pointer. So it will look something like: alias void* MY_CLASS; extern(C) MY_CLASS createMyClass() { return new MyClass; } Every method of your class like void myMethod(float arg); will need a plain function wrapper like extern(C) void myClassMyMethod(MY_CLASS self, float arg); And they'll all be implemented mostly like extern(C) void myClassMyMethod(MY_CLASS self, float arg) { MyClass real_self = cast(MyClass)self; // [check that it really is a MyClass] real_self.myMethod(arg); } And you will need a destroy call that takes a MY_CLASS, too, and calls the destructor. You also have to do something about any arguments or return values that are not C types and convert them accordingly. For instance if you have a method that returns a 'real' the C wrapper needs to cast it to double. I'm not sure if the GC will work normally or not. But I'm pretty sure you'll need to do something to startup and initialize the GC on the D side. Check out WinMain in http://www.dsource.org/projects/minwin/browser/trunk/minwin/app.d at line 144. In particular the calls to gc_init(), _minit(), _moduleCtor() and _moduleUnitTests(). Calling D from C/C++ is not something I have not done either, but will probably want to do at some point. So I'm also very interested in hearing about whether you succeed. And the above is what I was planning to try when I get to that point. If you're making a DLL out of the D code, then all the functions should be marked 'export' also so that they get marked as callable in the DLL. --bb
Feb 16 2007
next sibling parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Bill Baxter" <dnewsgroup billbaxter.com> wrote in message 
news:er58l2$i21$1 digitalmars.com...
 I'm not sure if the GC will work normally or not.  But I'm pretty sure 
 you'll need to do something to startup and initialize the GC on the D 
 side.  Check out WinMain in 
 http://www.dsource.org/projects/minwin/browser/trunk/minwin/app.d at line 
 144.  In particular the calls to gc_init(), _minit(), _moduleCtor() and 
 _moduleUnitTests().

The GC should work normally, but one thing you have to do is to make sure you keep references to any GC memory (i.e. anything allocated with 'new' in your D code) in the DLL. One way of doing this for classes is to keep a static list or AA of all instances of the class in the class: class ExportedClass { static bool[ExportedClass] instances; this() { .... instances[this] = true; } ~this() { instances.remove(this); } } This way, there is at least one reference to each class instance held in the DLL, so that the instances won't get collected. When the instances are deleted, they are removed from the list.
Feb 16 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Jarrett Billingsley wrote:
 "Bill Baxter" <dnewsgroup billbaxter.com> wrote in message 
 news:er58l2$i21$1 digitalmars.com...
 I'm not sure if the GC will work normally or not.  But I'm pretty sure 
 you'll need to do something to startup and initialize the GC on the D 
 side.  Check out WinMain in 
 http://www.dsource.org/projects/minwin/browser/trunk/minwin/app.d at line 
 144.  In particular the calls to gc_init(), _minit(), _moduleCtor() and 
 _moduleUnitTests().

The GC should work normally, but one thing you have to do is to make sure you keep references to any GC memory (i.e. anything allocated with 'new' in your D code) in the DLL. One way of doing this for classes is to keep a static list or AA of all instances of the class in the class: class ExportedClass { static bool[ExportedClass] instances; this() { .... instances[this] = true; } ~this() { instances.remove(this); } } This way, there is at least one reference to each class instance held in the DLL, so that the instances won't get collected. When the instances are deleted, they are removed from the list.

Ok, I wasn't sure about that. But it makes sense now. D memory allocated with 'new' is in some big D gc pool, and that's the only memory the GC scans for outstanding references. Well, that and stuff on the D stack. Anything in C land won't be noticed by the GC. Makes sense. --bb
Feb 16 2007
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
Bill Baxter wrote:
 
 I'm not sure if the GC will work normally or not.  But I'm pretty sure 
 you'll need to do something to startup and initialize the GC on the D 
 side.  Check out WinMain in 
 http://www.dsource.org/projects/minwin/browser/trunk/minwin/app.d at 
 line 144.  In particular the calls to gc_init(), _minit(), _moduleCtor() 
 and _moduleUnitTests().

And please be aware that the necessary sequence of function calls is different for GDC. Fixing this has been on my "to do" list for Tango since the project began, and it really all just comes down to finding an appropriate pair of function names. They will most likely be cr_init() and cr_term(), and will call the normal runtime initialization and termination process. I think I haven't gotten around to it yet simply because no one has complained about it :-) Sean
Feb 16 2007
parent Mn <mn mailinator.com> writes:
Sean Kelly Wrote:
 I think I haven't gotten around to it yet simply 
 because no one has complained about it :-)

*complain*
Feb 17 2007