www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Binding C++ Value Type (Templates)

reply "Benjamin Thaut" <code benjamin-thaut.de> writes:
There are currently two problems with binding c++ value types and 
c++ value type templates.

1. Semantics are somewhat different. Copying / constructor / 
destructing / operator overloading is a issue.
2. Only templates which are instantiated on the c++ side can be 
used.

Now it would be nice if I could tell a type, that it should be 
mangled like a C++ type but only if it is used in a C++ function 
signature. The entire type would still be implemented on the D 
side and the implementor would have to garantuee that the binary 
layout is the same as on the C++ side.

e.g.

extern(C++, wrapper)
struct SomeVector //mangling exactly like any other D type
{
   this(this)
   {
     D-Style copy code
   }

   void opBinary(string op)(ref SomeVector rh) if(op == "+")
   {
     D-Style operator overloading
   }
}

// In extern C++ decalrations SomeVector is mangled as C++ type.
extern(C++) SomeFunction(SomeVector vec);

That way you could mirror the implementation of Value Types on 
the D side using all D features available. Only the binary layout 
and size of the data members would have to be the same. But it 
would allow to pass value types between D and C++ and use them on 
both sides without the need to write wrapper functions which 
convert from a C++ value type to a D value type.

What do you think?

Kind Regards
Benjamin Thaut
Feb 13 2015
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Benjamin Thaut"  wrote in message 
news:mzgymsfzrxbvffgcfzxz forum.dlang.org...

 There are currently two problems with binding c++ value types and c++ 
 value type templates.

 1. Semantics are somewhat different. Copying / constructor / destructing / 
 operator overloading is a issue.
 2. Only templates which are instantiated on the c++ side can be used.

 Now it would be nice if I could tell a type, that it should be mangled 
 like a C++ type but only if it is used in a C++ function signature. The 
 entire type would still be implemented on the D side and the implementor 
 would have to garantuee that the binary layout is the same as on the C++ 
 side.
You don't need to tell the type anything, this is how all structs work by default. One thing you need to be very careful about is making sure that both languages see the struct as POD or non-POD, otherwise they may disagree on how to pass it to/return it from functions. What problems have you been having with this approach?
Feb 13 2015
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 13.02.2015 um 19:40 schrieb Daniel Murphy:
 "Benjamin Thaut"  wrote in message
 news:mzgymsfzrxbvffgcfzxz forum.dlang.org...

 There are currently two problems with binding c++ value types and c++
 value type templates.

 1. Semantics are somewhat different. Copying / constructor /
 destructing / operator overloading is a issue.
 2. Only templates which are instantiated on the c++ side can be used.

 Now it would be nice if I could tell a type, that it should be mangled
 like a C++ type but only if it is used in a C++ function signature.
 The entire type would still be implemented on the D side and the
 implementor would have to garantuee that the binary layout is the same
 as on the C++ side.
You don't need to tell the type anything, this is how all structs work by default. One thing you need to be very careful about is making sure that both languages see the struct as POD or non-POD, otherwise they may disagree on how to pass it to/return it from functions. What problems have you been having with this approach?
Well, it doesn't work for anything that is within an C++ namespace. Example: C++: namespace Test { struct IntVector { private: int* _data; size_t _size; public: IntVector(size_t size) { _size = size; _data = (int*)malloc(sizeof(int) * size); } IntVector(const IntVector& other) { _size = other._size; _data = (int*)malloc(sizeof(int) * _size); memcpy(_data, other._data, sizeof(int) * _size); } int operator[](size_t index) { return _data[index]; } int* begin() { return _data; } int* end() { return _data + _size; } }; void ProcessIntVector(IntVector& v) { for (auto& i : v) { i++; } } } D: extern(C++, Test) { struct IntVector { private: int[] _data; public: this(size_t size) { _data = (cast(int*)malloc(int.sizeof * size))[0..size]; } this(this) { auto oldData = _data; _data = (cast(int*)malloc(int.sizeof * oldData.length))[0..oldData.length]; _data[] = oldData[]; } int opIndex(size_t index) { return _data[index]; } int[] data() { return _data; } alias data this; } void ProcessIntVector(ref IntVector v); } If I remove the "Test" namespace everything works as expected. Kind Regards Benjamin Thaut
Feb 15 2015
parent reply "Daniel Murphy" <yebbliesnospam gmail.com> writes:
"Benjamin Thaut"  wrote in message news:mbq03u$2h5v$1 digitalmars.com...

 Well, it doesn't work for anything that is within an C++ namespace.

 If I remove the "Test" namespace everything works as expected.
I think what you want is something along these lines: D: extern(C++, Test) { extern(D) struct IntVector { ... } void ProcessIntVector(ref IntVector v); } I don't like the way namespaces are conflated with linkage changes but I lost that argument. This is essentially saying "I just want the namespace part of the extern(C++)".
Feb 15 2015
parent reply Benjamin Thaut <code benjamin-thaut.de> writes:
Am 15.02.2015 um 13:59 schrieb Daniel Murphy:
 "Benjamin Thaut"  wrote in message news:mbq03u$2h5v$1 digitalmars.com...

 Well, it doesn't work for anything that is within an C++ namespace.

 If I remove the "Test" namespace everything works as expected.
I think what you want is something along these lines: D: extern(C++, Test) { extern(D) struct IntVector { ... } void ProcessIntVector(ref IntVector v); } I don't like the way namespaces are conflated with linkage changes but I lost that argument. This is essentially saying "I just want the namespace part of the extern(C++)".
Oh wow, that actually compiles. Thanks very much. Maybe this should be documented on the "Interfacing to C++" page.
Feb 15 2015
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 2/15/15 5:33 AM, Benjamin Thaut wrote:
 Maybe this should be documented on the "Interfacing to C++" page.
Pull request pliz pliz -- Andrei
Feb 15 2015
parent Benjamin Thaut <code benjamin-thaut.de> writes:
Am 15.02.2015 um 17:25 schrieb Andrei Alexandrescu:
 On 2/15/15 5:33 AM, Benjamin Thaut wrote:
 Maybe this should be documented on the "Interfacing to C++" page.
Pull request pliz pliz -- Andrei
Honestly, I'm currentyl preparing a really huge pull request for D (Dll support for windows) and I'm kind of upset that blocking issues that have come up during that pull request don't seem to be important enough to actually decide on them. This leaves me with a working Dll implementation, which I put a ton of work into, which is now blocked. My current fear is, that I will end up invensting all this work in vain and until that is settled, you won't be seeing any further pull request from my side. Kind Regards Benjamin Thaut
Feb 15 2015