2016-03-23 42 views
5

我正在嘗試與C++和D進行互操作。而今天我發現的東西真的搞亂了我的想法:在我的程序中沒有正確傳遞對象。如何將對象從D傳遞到C++?

最好展示一個例子。

我有一個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++庫,傳遞給在C++庫中創建的printer對象,並且此傳輸是在D程序中進行的。

而且結果是出乎意料的正確:

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

我失去了C的概念++和d互操作或這兩種d編譯器(疑惑)一個錯誤?

+2

AFAIK這是由設計。 D能夠連接到C++,但不能自行創建C++對象(並且D對象具有不同的二進制佈局)。使用工廠方法似乎正確。 –

回答

3

如果你創建一個Color :: getInstance,你不應該使用Ds new來分配C++類。

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文檔中有一個參考:http://dlang.org/spec/cpp_interface.html#memory-allocation說'把一個指針留在堆棧(作爲參數或自動變量)'*(...是這類問題的解決方案...)* – shybovycha

+0

這是爲了與GC一起分配的對象,以防止它們被收集,因爲GC不知道C++仍然具有對這些對象的引用。例如,如果您將GC分配的對象存儲在C++數組中。 – NotSpooky

相關問題