View mode: basic / threaded / horizontal-split · Log in · Help
February 16, 2007
Re: Writing a library
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
February 16, 2007
Re: Writing a library
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
>> 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

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
February 16, 2007
Re: Writing a library
"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.
February 17, 2007
Re: Writing a library
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
February 17, 2007
Re: Writing a library
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
February 17, 2007
Re: Writing a library
Sean Kelly Wrote:
> I think I haven't gotten around to it yet simply 
> because no one has complained about it :-)

*complain*
Top | Discussion index | About this forum | D home