How to pass an object from D to C ++?

I am trying to do interop with C ++ and D. And what I found today really confuses my mind: objects are not being transferred correctly in my program.

Better to show an example.

I have a C ++ library that I compile into an object file and a D program that I link to my library and run.

Here they are:

#include <stdio.h> class Color { public: Color(unsigned int _r, unsigned int _g, unsigned int _b) : r(_r), g(_g), b(_b) {} unsigned int r, g, b; }; class Printer { public: Printer() {} ~Printer() {} static Printer* getInstance(); void print(Color *c); }; Printer* Printer::getInstance() { return new Printer(); } void Printer::print(Color *c) { printf("(%d, %d, %d)\n", c->r, c->g, c->b); } 

And program D:

 import std.stdio; extern(C++) { class Color { uint r, g, b; this(uint _r, uint _g, uint _b) { r = _r; g = _g; b = _b; } } class Printer { @disable this(); static Printer getInstance(); final void print(Color c); } } void main() { auto printer = Printer.getInstance(); Color c = new Color(42, 7, 19); printer.print(c); } 

I will compile them with the following commands:

 c++ -c my_core.cpp -o my_core.o dmd main.d my_core.o -L-lstdc++ 

But when I started ./main , I got strange results:

 (113244372, 1, 42) 

What made me think that objects are being transmitted incorrectly is just an experiment. Firstly, I ran my program a couple of times, and this is what I saw:

 $ ./main (266442332, 1, 42) $ ./main (234899036, 1, 42) $ ./main (109475420, 1, 42) 

So, the first number looks like a pointer to a block of memory. And my sixth sense paired with build knowledge makes me think it's a pointer to the this variable.

And now, to confirm that my data still exists, and that these numbers are not random, I added two more fields to my Color class:

C ++ lib:

 #include <stdio.h> class Color { public: Color(unsigned int _r, unsigned int _g, unsigned int _b, unsigned int _u, unsigned int _v) : r(_r), g(_g), b(_b), u(_u), v(_v) {} unsigned int r, g, b, u, v; }; class Printer { public: Printer() {} ~Printer() {} static Printer* getInstance(); void print(Color *c); }; Printer* Printer::getInstance() { return new Printer(); } void Printer::print(Color *c) { printf("(%d, %d, %d, %d, %d)\n", c->r, c->g, c->b, c->u, c->v); } 

And program D:

 import std.stdio; extern(C++) { class Color { this(uint _r, uint _g, uint _b, uint _u, uint _v) { r = _r; g = _g; b = _b; u = _u; v = _v; } uint r, g, b, u, v; } class Printer { @disable this(); static Printer getInstance(); final void print(Color c); } } void main() { auto printer = Printer.getInstance(); Color c = new Color(42, 7, 19, 499, 727); printer.print(c); } 

And outputs:

 $ ./main (90379876, 1, 42, 7, 19) $ ./main (79758948, 1, 42, 7, 19) $ ./main (74901092, 1, 42, 7, 19) $ ./main (217458276, 1, 42, 7, 19) $ ./main (238933604, 1, 42, 7, 19) 

I tried to compile my program with both DMD and LDC compilers, but both provided me with exactly the same behavior.

UPD: What is even more interesting and (possibly) indicates where the problem lies is the fact that objects created in C ++ lib are passed between D and C ++ correctly.

To prove this, I created a factory method in the Color class:

 static Color* create(unsigned int _r, unsigned int _g, unsigned int _b, unsigned int _u, unsigned int _v) { return new Color(_r, _g, _b, _u, _v); } 

And then in program D:

 Color c = Color.create(42, 7, 19, 499, 727); printer.print(c); 

So, the object c comes from the C ++ library, is passed to the printer object created in the C ++ library, and this transfer is performed in the program D.

And the results are unexpectedly true:

 $ ./main (42, 7, 19, 499, 727) 

Am I missing the concepts of C ++ and D interop or is it a mistake in two D compilers (with doubt)?

+5
source share
1 answer

You should not use Ds new to highlight C ++ classes, if you create Color :: getInstance, it works.

 import std.stdio; extern(C++) { class Color { this(uint _r, uint _g, uint _b, uint _u, uint _v) { r = _r; g = _g; b = _b; u = _u; v = _v; } uint r, g, b, u, v; static Color getInstance(uint _r, uint _g, uint _b, uint _u, uint _v); } class Printer { @disable this(); static Printer getInstance(); final void print(Color c); } } void main() { auto printer = Printer.getInstance(); auto c = Color.getInstance(42, 7, 19, 499, 727); printer.print(c); } 

and

 #include <stdio.h> class Color { public: Color(unsigned int _r, unsigned int _g, unsigned int _b, unsigned int _u, unsigned int _v) : r(_r), g(_g), b(_b), u(_u), v(_v) {} unsigned int r, g, b, u, v; static Color* getInstance (unsigned int _r, unsigned int _g, unsigned int _b, unsigned int _u, unsigned int _v); }; Color* Color::getInstance(unsigned int _r, unsigned int _g, unsigned int _b, unsigned int _u, unsigned int _v) { return new Color(_r, _g, _b, _u, _v); } class Printer { public: Printer() {} ~Printer() {} static Printer* getInstance(); void print(Color *c); }; Printer* Printer::getInstance() { return new Printer(); } void Printer::print(Color *c) { printf("(%d, %d, %d, %d, %d)\n", c->r, c->g, c->b, c->u, c->v); } 
+3
source

Source: https://habr.com/ru/post/1245670/


All Articles