February 16, 2007
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
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
"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
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
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
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