Я пытаюсь сделать взаимодействие с C ++ и D. И то, что я нашел сегодня, действительно запутывает меня: объекты не передаются правильно в моей программе.
Лучше показать пример.
У меня есть библиотека C ++, которую я компилирую в объектный файл и программу D, которую я связываю со своей библиотекой и запускаю.
Вот они:
#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);
}
И программа 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);
}
Я компилирую их с помощью этих команд:
c++ -c my_core.cpp -o my_core.o
dmd main.d my_core.o -L-lstdc++
Но когда я бегу ./main
Я получил странные результаты:
(113244372, 1, 42)
То, что заставило меня думать, что объекты передаются неправильно, — это просто эксперимент. Сначала я пару раз запускал свою программу, и вот что я увидел:
$ ./main
(266442332, 1, 42)
$ ./main
(234899036, 1, 42)
$ ./main
(109475420, 1, 42)
Таким образом, первое число кажется указателем на блок памяти. И мое шестое чувство в паре с знанием сборки заставляет меня думать, что это указатель на this
переменная.
И теперь, чтобы подтвердить, что мои данные все еще на месте и эти числа не просто случайные, я добавил еще два поля в свой класс Color
:
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);
}
И программа 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);
}
И выходы:
$ ./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)
Я пытался скомпилировать свою программу с компиляторами DMD и LDC, но оба предоставили мне абсолютно одинаковое поведение.
UPD: Что еще интереснее и (наверное) указание на то, в чем заключается проблема, заключается в том, что объекты факта, созданные в C ++ lib, правильно передаются между D и C ++.
Чтобы доказать это, я создал «фабричный метод» в своем Color
учебный класс:
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);
}
И тогда, в программе D:
Color c = Color.create(42, 7, 19, 499, 727);
printer.print(c);
Таким образом c
объект поступает из библиотеки C ++, передается в printer
объект, созданный в библиотеке C ++, и эта передача производится в программе D.
И результаты неожиданно верны:
$ ./main
(42, 7, 19, 499, 727)
Я скучаю по понятиям взаимодействия C ++ и D или это ошибка в двух компиляторах D (Недоверчиво)?
Вы не должны использовать Ds new для размещения классов C ++, если вы создаете Color :: getInstance, это работает.
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);
}
а также
#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);
}
Других решений пока нет …