Quonux
Quonux

Reputation: 2991

C++ to D interoperability

Since days im trying to call some D code from C++ (with an class/interface defined for C++ and D).

the D code

module BufferCppBinding;

extern (C++) void *createBufferCppBinding() {
    BufferCppBinding ptr = new BufferCppBinding();
    return cast(void*)ptr;
}

extern (C++) interface BufferCppBindingInterface {
    void construct();
    // ...
}

class BufferCppBinding : BufferCppBindingInterface {
    public Buffer thisPtr;

    public extern (C++) void construct() {
        // doesn't do anything
    }
}

the C++ code for declaring the type to C++ land:

class BufferCppBinding {
public:

    virtual void construct();
};

for the initialisation of the D runtime i wrote a small function in D which does in D land:

extern (C++) void initDRuntime() nothrow{
    try
    {
        Runtime.initialize();
        //result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
        //Runtime.terminate(&exceptionHandler);
    }
    catch (Throwable o)
    {
        //MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
        //result = 0;
    }
}

usage (C++):

BufferCppBinding *vertexBuffer = reinterpret_cast<BufferCppBinding*>(createBufferCppBinding());

// here happens the crash
vertexBuffer->construct();

I am compiling the code with g++ 5.2 and ldc2 and linking it with ldc2.

I just get a SIGSEGV.

Upvotes: 4

Views: 168

Answers (1)

&#193;tila Neves
&#193;tila Neves

Reputation: 1412

Returning pointers to C++ that point to the GC heap is a bad idea - use malloc/emplace (or std.experimental.allocator.make) instead and callfreeon the C++ side. That won't run destructors though, so maybe you want to expose a D function that callsdestroy` as well.

BTW, no need to return void* and cast back - just return BufferCppBindingInterface from createBufferCppBinding.

Upvotes: 2

Related Questions