Binding C++ Value Type (Templates)

Benjamin Thaut via Digitalmars-d digitalmars-d at puremagic.com
Sun Feb 15 03:32:15 PST 2015


Am 13.02.2015 um 19:40 schrieb Daniel Murphy:
> "Benjamin Thaut"  wrote in message
> news:mzgymsfzrxbvffgcfzxz at 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


More information about the Digitalmars-d mailing list