Why using wrappers for D?

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Oct 3 11:11:31 PDT 2016


On 10/03/2016 05:47 AM, Chalix wrote:

 > what do you mean
 > by "turn C functions into classes"?

Many C APIs are object-oriented in that, they pass the most interesting 
object as the first parameter:

// C struct
struct Foo {
     // ...
};

// Factory method (or, "constructor")
Foo* make_foo(int i, double d);

void free_foo(Foo** foo);

int use_foo(Foo* foo, const char *str);

Instead of living with C's limitations, one can define a D struct Foo 
and turn such function into member functions:

// D struct
struct FooD {
     // ...
     Foo* c_foo;
     // other things that go with

     // Factory method (or, "constructor")
     this(int i, double d) {
         c_foo = make_foo(i, d);    // dispatch to C library
     }

     ~this() {
         free_foo(&c_foo);    // dispatch to C library
     }

     void use(BarD bar) {
         enforce(use_foo(c_foo, "hello");
     }
}

That's how a D wrapper of a C library may look like, which should be 
almost identical to how it could be done in C++.

 > Also, I used the Qt library a lot with C++. But although it is a
 > library, I have access to all the classes, like " QWidget w = new
 > QWidget();". There is no factory method used. (This confuses me now a
 > bit...)

'new QWidget()' does call the constructor automatically, which D cannot 
do. (Although, with the recent changes in C++ interoperability, perhaps 
even that's doable today.)

If D cannot create C++ object with the 'new' keyword, then they can use 
a layer of a factory method to do it:

// A C++ layer
extern "C" QWidget* make_QWidget() {
     return new QWidget();
}

extern "C" void free_QWidget(QWidget* p) {
     delete p;
}

Since that function (i.e. not the "new expression" itself) is callable 
from D, the D code can now use the library:

extern (C) {
// ...
QWidget* make_QWidget();
void free_QWidget(QWidget* p);
}

// D class
class QWidgetD
{
     QWidget* cpp_widget;

     this() {
         cpp_widget = make_QWidget();
     }

     ~this() {
         free_QWidget(cpp_widget);
     }

     // ...
}

That's how I understand it anyway... :) Again though, this may be much 
easier today with the recent and ongoing improvements to C++ 
interoperability.

Ali



More information about the Digitalmars-d-learn mailing list