digitalmars.D.learn - C/C++ struct interfacing
- Oleg B (50/50) Oct 27 2013 Hello.
- =?UTF-8?B?IlLDqW15IE1vdcOremEi?= (36/86) Oct 31 2013 Below is a solution to get it to work as a C binding.
Hello.
I want use one struct in two language.
How to declare the same structure in different languages?
D code: calling C++ function with my struct
<code>
extern(C++)
{
     struct vec(size_t N, T=float)
     { // << line 6
         alias vec!(N,T) thistype;
         T[N] data;
         auto opBinary(string op)( in thistype rhs ) const
         {
             thistype ret;
             foreach( i; 0 .. N ) ret.data[i] = data[i] + 
rhs.data[i];
             return ret;
         }
     }
     void cppcall( vec!(3,float) d );
}
void main()
{
     vec!3 a, b;
     a.data[0] = 10;
     a.data[1] = 7;
     a.data[2] = 3;
     b.data[0] = 13;
     b.data[1] = 9;
     b.data[2] = 4;
     cppcall( a + b );
}
</code>
C++ code: use struct data
<code>
#include <cstdio>
struct vec
{
     float data[3];
};
void cppcall( vec d )
{
     printf( "%f %f %f\n", d.data[0], d.data[1], d.data[2] );
}
</code>
compilation failed with unclear error
$ g++ -c ctypestest.cpp -o ctypestest.o
$ dmd ctypestest.d ctypestest.o -ofctypestest
ctypestest.d(6): Error: struct ctypestest.vec!(3, float).vec C++ 
static variables not supported
 Oct 27 2013
Below is a solution to get it to work as a C binding.
- Your structure should not be enclosed in the `extern (C)` 
block; leave it as regular D code.
- cppcall should be declared `extern (C)` in D and `extern "C"` 
in C++;
- depending on your platform, you need to link to the C++ 
standard lib ; on my Ubuntu 12.04, I added the `-L-lstdc++` on 
the dmd command line.
I already used that pattern in some binding for the RtMidi lib:
https://github.com/remy-j-a-moueza/drtmidi
dRtMidi.d defines a templated structure :
struct answer (T) {
     int success;
     T value;
     const (char) * errMsg;
}
and so does cRtMidi.cpp :
template <typename T>
struct answer {
     int success;
     T value;
     const char * errMsg;
};
I declared a bunch of `extern (C)` and `extern "C"` function that 
pass that data arround. It works only if the T data type as the 
same size in both languages.
You can check the size correspondance on this page : 
http://dlang.org/interfaceToC.html
And for more tricky types, you can get some inspiration from 
Jacob Carlborg dstep project, especially :
- translateType () in Type.d : 
https://github.com/jacob-carlborg/dstep/blob/master/dstep/translator/Type.d
- and the static constructor of the IncludeHandler class, to get 
to import the right D core module : 
https://github.com/jacob-carlborg/dstep/blob/master/dstep/translator/IncludeHandler.d
On Sunday, 27 October 2013 at 12:20:49 UTC, Oleg B wrote:
 Hello.
 I want use one struct in two language.
 How to declare the same structure in different languages?
 D code: calling C++ function with my struct
 <code>
 extern(C++)
 {
     struct vec(size_t N, T=float)
     { // << line 6
         alias vec!(N,T) thistype;
         T[N] data;
         auto opBinary(string op)( in thistype rhs ) const
         {
             thistype ret;
             foreach( i; 0 .. N ) ret.data[i] = data[i] + 
 rhs.data[i];
             return ret;
         }
     }
     void cppcall( vec!(3,float) d );
 }
 void main()
 {
     vec!3 a, b;
     a.data[0] = 10;
     a.data[1] = 7;
     a.data[2] = 3;
     b.data[0] = 13;
     b.data[1] = 9;
     b.data[2] = 4;
     cppcall( a + b );
 }
 </code>
 C++ code: use struct data
 <code>
 #include <cstdio>
 struct vec
 {
     float data[3];
 };
 void cppcall( vec d )
 {
     printf( "%f %f %f\n", d.data[0], d.data[1], d.data[2] );
 }
 </code>
 compilation failed with unclear error
 $ g++ -c ctypestest.cpp -o ctypestest.o
 $ dmd ctypestest.d ctypestest.o -ofctypestest
 ctypestest.d(6): Error: struct ctypestest.vec!(3, float).vec 
 C++ static variables not supported
 Oct 31 2013








 
  
  
  =?UTF-8?B?IlLDqW15IE1vdcOremEi?= <remy.moueza gmail.com>
 =?UTF-8?B?IlLDqW15IE1vdcOremEi?= <remy.moueza gmail.com>