私はC++とDとの相互運用をしようとしています。今日発見したことは、私のプログラムでオブジェクトが正しく渡されていないということです。DからC++にオブジェクトを渡すには?
例を示すことをお勧めします。
私はオブジェクトファイルとライブラリにリンクして実行するDプログラムにコンパイルするC++ライブラリを持っています。
ここで彼らは、次のとおりです。私はこれらのコマンドでそれらをコンパイル
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
を実行したとき、私は奇妙だ
#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プログラム結果:
(113244372, 1, 42)
私は、オブジェクトが正しく渡されていないと思うのは、単なる実験に過ぎません。まず、私は数回私のプログラムを実行し、ここで私が見たものです:
$ ./main
(266442332, 1, 42)
$ ./main
(234899036, 1, 42)
$ ./main
(109475420, 1, 42)
だから、最初の数は、メモリブロックへのポインタのようです。アセンブリの知識を持つカップルで私の6番目の気持ちは、それがthis
変数へのポインタだと思うようになります。
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);
}
私は私のクラス
Color
にさらに2つのフィールドを追加しました、
そして今、私のデータを確認するには、場所にまだあると、これらの数字は、単にランダムなものではありません
そして、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++正しく間で渡されているです。 Dプログラムでは、その後、
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);
}
そして:これを証明するために
は、私は私のColor
クラスの "ファクトリメソッド" を作成し
Color c = Color.create(42, 7, 19, 499, 727);
printer.print(c);
c
オブジェクトはC++ライブラリから来るように、 C++ライブラリで作成されたprinter
オブジェクトに渡され、この転送はDプログラムで行われます。
そして、結果は予想外に正しいです:
$ ./main
(42, 7, 19, 499, 727)
(疑わし)私は相互運用C++とDの概念を欠落しているか、これは2つのDコンパイラのバグであるだろうか?
仕様です。 DはC++にインターフェイスすることはできますが、C++オブジェクトを独自に作成することはできません(Dオブジェクトは異なるバイナリレイアウトを持ちます)。ファクトリメソッドを使用するのが正しいようです。 –