2016-03-23 12 views
5

私は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コンパイラのバグであるだろうか?

+2

仕様です。 DはC++にインターフェイスすることはできますが、C++オブジェクトを独自に作成することはできません(Dオブジェクトは異なるバイナリレイアウトを持ちます)。ファクトリメソッドを使用するのが正しいようです。 –

答えて

3

Color :: getInstanceを作成すると、C++クラスを割り当てるのにDs newを使うべきではありません。この私の知る限り

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); 
} 
+0

しかし、それはバイパス問題のように聞こえるのですか?D docsには、http://dlang.org/spec/cpp_interface.html#memory-allocationというリファレンスがあります。スタック(パラメータまたは自動変数として) '*(...はこの種の問題に対する解決策です)* – shybovycha

+0

これは、GCが割り当てられていないために収集されないオブジェクトC++にはまだこれらのオブジェクトへの参照があります。たとえば、GCに割り当てられたオブジェクトをC++配列に格納するとします。 – NotSpooky

関連する問題