2016-03-23 18 views
5

Tôi đang cố gắng làm cho một interop với C + + và D. Và điều tôi đã tìm thấy ngày hôm nay là thực sự rối tung tâm trí của tôi: các đối tượng không được thông qua một cách chính xác trong chương trình của tôi.Làm cách nào để truyền đối tượng từ D sang C++?

Tốt hơn là hiển thị ví dụ.

Tôi có thư viện C++, mà tôi biên dịch thành tệp đối tượng và chương trình D, mà tôi liên kết với thư viện của mình và chạy.

Dưới đây là:

#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); 
} 

Và chương trình 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); 
} 

tôi biên dịch chúng bằng các lệnh:

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

Nhưng khi tôi chạy ./main, tôi đã kỳ lạ kết quả:

(113244372, 1, 42) 

Điều gì khiến tôi nghĩ rằng các đối tượng đang được chuyển không chính xác chỉ là một thử nghiệm đơn giản. Trước tiên, tôi đã chạy chương trình của mình một vài lần và đây là những gì tôi đã thấy:

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

Vì vậy, số đầu tiên dường như là con trỏ đến khối bộ nhớ. Và cảm giác thứ sáu của tôi trong cặp vợ chồng với kiến ​​thức lắp ráp làm cho tôi nghĩ rằng đó là con trỏ đến biến this.

Và bây giờ, chỉ để xác nhận dữ liệu của tôi vẫn được đặt ra và những con số này không chỉ những người ngẫu nhiên, tôi đã thêm hơn hai lĩnh vực để lớp học của tôi 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); 
} 

Và chương trình 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); 
} 

Và kết quả đầu ra là:

$ ./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) 

Tôi đã thử biên dịch chương trình của mình bằng cả trình biên dịch DMD và LDC, nhưng cả hai đều cung cấp cho tôi chính xác cùng một hành vi.

UPD: gì thậm chí còn thú vị hơn và (có lẽ) trỏ đến nơi mà vấn đề nằm, là các đối tượng thực tế, tạo ra trong lib C++ đang được thông qua giữa D và C++ một cách chính xác.

Để chứng minh điều này, tôi tạo ra "phương pháp nhà máy" trong lớp Color tôi:

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

Và sau đó, trong chương trình D:

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

printer.print(c); 

Vì vậy mà đối tượng c xuất phát từ thư viện C++, được chuyển đến đối tượng printer, được tạo trong thư viện C++ và quá trình truyền này được thực hiện trong chương trình D.

Và kết quả là bất ngờ đúng:

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

Tôi có thiếu các khái niệm về C++ và D interop hay đây là một lỗi trong hai trình biên dịch D (hồ nghi)?

+2

AFAIK này là do thiết kế. D có khả năng giao tiếp với C++ nhưng nó không thể tạo các đối tượng C++ trên chính nó (và các đối tượng D có bố cục nhị phân khác nhau). Sử dụng phương pháp nhà máy có vẻ đúng. –

Trả lời

3

Bạn không nên sử dụng Ds mới để phân bổ các lớp C++, nếu bạn tạo Màu :: getInstance, nó hoạt động.

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

Nhưng điều đó nghe có vẻ như bỏ qua vấn đề, phải không? .. Có một tài liệu tham khảo về các tài liệu D: http://dlang.org/spec/cpp_interface.html#memory-allocation nói 'Để lại một con trỏ đến nó trên stack (như một tham số hoặc biến tự động) '* (... là một giải pháp cho loại vấn đề này ...) * – shybovycha

+0

Đó là cho các đối tượng được phân bổ với GC để ngăn chúng không được thu thập vì GC không biết C++ vẫn có tham chiếu đến các đối tượng đó. Ví dụ, nếu bạn lưu trữ một đối tượng được cấp phát GC trên một mảng C++. – NotSpooky

Các vấn đề liên quan