Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D programming : interface at component boundaries

Tags:

c++

interface

d

C++ relies heavily on C style to export and import functions (not classes / interfaces if there was one) thus loosing the object oriented flavour that in many ways makes the exported interface cryptic.

Can D programming language be used to export interfaces in a object oriented style. Can I wrap C++ (pure)classes with D interfaces ? What are the possible elements to consider ? Is this approach feasible.

like image 630
Ram Avatar asked Apr 10 '12 04:04

Ram


1 Answers

You can find an overview over D's C++ interoperability spectrum here.

Object-oriented style interoperability is provided through D's interface construct:

C++ side

#include<iostream>

class I // Our interface-by-convention
{
public:
    virtual void foo() = 0;

    void bar() // OK, non-virtual members do not affect binary compatibility
    {
        /* ... */
    }
};

class C : public I
{
private:
    int a;

public:
    C(int a) : a(a) {}

    void foo()
    {
        std::cout << a << std::endl;
    }
};

// This function will be used from the D side
I* createC(int a)
{
    return new C(a);
}

D side

extern(C++) interface I
{
    void foo();

    final void bar() // OK, non-virtual members do not affect binary compatibility
    {
        /+ ... +/
    }
}

// Link `createC` from the C++ side
extern(C++) I createC(int a);

void main()
{
    I i = createC(2);
    i.foo(); // Write '2' to stdout
}

D's extern(C++) on the interface I causes the interface layout to replicate the layout of a single-inheritance C++ class with virtual functions in the companion C++ compiler.

The same attribute on the function declaration createC causes the function to replicate the mangling and calling convention of an equivalent function in the companion C++ compiler.

Companion compiler pairs: DMD/DMC++, GDC/g++, LDC/Clang. It's often possible to interoperate with a non-companion compiler by sticking to virtual functions and the C ABI for direct function calls.

Note that the createC function returns I* in C++ and just I in D. This is because D interfaces and classes are implicitly reference types.

In more typical real-world use, the createC function is more likely to be extern(C) than extern(C++) (and then extern "C" on the C++ side), for greater interoperability between compilers, or more straight-forward runtime linking when using DLLs.

extern(C++) currently has some limitations; it's currently not possible to tell D which namespace an extern(C++) declaration is in, limiting D to only being able to link to C++ symbols in the global namespace.

like image 200
jA_cOp Avatar answered Sep 30 '22 23:09

jA_cOp