digitalmars.D.learn - Using C++ Classes From D: dmd cannot link, while ldc segfault
- mw (122/122) Jun 18 2023 Hi,
- Richard (Rikki) Andrew Cattermole (2/2) Jun 18 2023 This is just a guess, but I think the problem is the vtable is incomplet...
- mw (14/18) Jun 18 2023 So, you mean on the D side, it need to list all the fields and
- mw (9/12) Jun 18 2023 A related question: basically I want to pass an array of objects
- Richard (Rikki) Andrew Cattermole (6/8) Jun 18 2023 Yes, you would also need to verify it with every compiler you need
- mw (4/11) Jun 18 2023 Ha, I saw vector.d there, So I can use this vector.d as the D
- Richard (Rikki) Andrew Cattermole (3/5) Jun 18 2023 Probably, I just don't know how well tested it is.
Hi, I'm following this example: https://dlang.org/spec/cpp_interface.html#using_cpp_classes_from_d and try to wrap a std::list base.cpp ```cpp #include <iostream> #include <list> using namespace std; class Base { public: virtual void print3i(int a, int b, int c) = 0; }; class Derived : public Base { public: int field; Derived(int field) : field(field) {} void print3i(int a, int b, int c) { cout << "a = " << a << endl; cout << "b = " << b << endl; cout << "c = " << c << endl; } int mul(int factor); }; template<class T> class std_list : public std::list<T> {}; void getInts(std_list<int>* list); int Derived::mul(int factor) { return field * factor; } Derived *createInstance(int i) { // get list of ints from D side std_list<int> list; list.push_back(911); ::getInts(&list); for (int i : list) { cout << "i = " << i << endl; } return new Derived(i); } void deleteInstance(Derived *&d) { delete d; d = 0; } ``` main.c ``` extern(C++) { abstract class Base { void print3i(int a, int b, int c); } class Derived : Base { int field; disable this(); override void print3i(int a, int b, int c); final int mul(int factor); } Derived createInstance(int i); void deleteInstance(ref Derived d); } extern(C++) { class std_list(T) { disable this(); void push_back(const ref T value); } void getInts(std_list!(int) list) { foreach (int i; 0 .. 10) { list.push_back(i); } } } void main() { import std.stdio; auto d1 = createInstance(5); writeln(d1.field); writeln(d1.mul(4)); Base b1 = d1; b1.print3i(1, 2, 3); deleteInstance(d1); assert(d1 is null); auto d2 = createInstance(42); writeln(d2.field); deleteInstance(d2); assert(d2 is null); } ``` Makefile ``` c2d: g++ -c -g -ggdb base.cpp ldmd2 -g main.d base.o -L-lstdc++ && ./main ``` if I use LCD (ldmd2), it segfaults: ``` $ make g++ -c -g -ggdb base.cpp ldmd2 -g main.d base.o -L-lstdc++ && ./main Segmentation fault (core dumped) ``` and gdb shows it fails at: main.d:29 list.push_back(i); if I use DMD, it cannot link: ``` $ make g++ -c -g -ggdb base.cpp dmd -g main.d base.o -L-lstdc++ && ./main /usr/bin/ld: main.o:(.data._D4main__T8std_listTiZQm6__vtblZ+0x0): undefined reference to `std_list<int>::push_back(int const&)' collect2: error: ld returned 1 exit status Error: linker exited with status 1 ``` Looks like something wrong with the push_back(). So, how to fix this DMD link error, and LDC segfaults? Thanks.
Jun 18 2023
This is just a guess, but I think the problem is the vtable is incomplete. Because of this the offsets are wrong. So you wouldn't be calling push_back.
Jun 18 2023
On Monday, 19 June 2023 at 05:32:23 UTC, Richard (Rikki) Andrew Cattermole wrote:This is just a guess, but I think the problem is the vtable is incomplete. Because of this the offsets are wrong. So you wouldn't be calling push_back.So, you mean on the D side, it need to list all the fields and methods of the C++ class? ```d class std_list(T) { disable this(); void push_back(const ref T value); } ``` Then it will be very tedious, esp. for such library class std::list. Is there a tool that can automate this? Thanks.
Jun 18 2023
On Monday, 19 June 2023 at 05:39:51 UTC, mw wrote:Then it will be very tedious, esp. for such library class std::list. Is there a tool that can automate this?A related question: basically I want to pass an array of objects from D side to the Cpp side, is there any example showing how to do this? On this page https://dlang.org/spec/cpp_interface.html#cpp-templates I did not find any information about passing array (containers) between D and Cpp. Thanks.
Jun 18 2023
On 19/06/2023 5:39 PM, mw wrote:Then it will be very tedious, esp. for such library class std::list.Yes, you would also need to verify it with every compiler you need (MSVC, vs linux gcc). There could be a reason why it isn't in https://github.com/dlang/dmd/tree/master/druntime/src/core/stdcppIs there a tool that can automate this?Not that I know of.
Jun 18 2023
On Monday, 19 June 2023 at 05:46:13 UTC, Richard (Rikki) Andrew Cattermole wrote:On 19/06/2023 5:39 PM, mw wrote:Ha, I saw vector.d there, So I can use this vector.d as the D side of C++'s std::vector?Then it will be very tedious, esp. for such library class std::list.Yes, you would also need to verify it with every compiler you need (MSVC, vs linux gcc). There could be a reason why it isn't in https://github.com/dlang/dmd/tree/master/druntime/src/core/stdcpp
Jun 18 2023
On 19/06/2023 5:54 PM, mw wrote:Ha, I saw vector.d there, So I can use this vector.d as the D side of C++'s std::vector?Probably, I just don't know how well tested it is. But worth a go!
Jun 18 2023
On Monday, 19 June 2023 at 05:56:54 UTC, Richard (Rikki) Andrew Cattermole wrote:On 19/06/2023 5:54 PM, mw wrote:``` import core.stdcpp.vector; extern(C++) { void getInts(core.stdcpp.vector.vector!(int) vec) { foreach (int i; 0 .. 10) { vec.push_back(i); } } } ``` dmd v2.104.0 failed: ``` /usr/include/dmd/druntime/import/core/stdcpp/vector.d(58): Error: undefined identifier `size`, did you mean alias `size_t`? /usr/include/dmd/druntime/import/core/stdcpp/vector.d(33): Error: template instance `core.stdcpp.vector.vector!(int, allocator!int)` error instantiating main.d(32): instantiated from here: `vector!int` ``` LDC - the LLVM D compiler (1.32.2): ``` main.d(32): Error: undefined identifier `vector` in module `core.stdcpp.vector`, did you mean enum member `MIctor`? ``` So what's wrong the LDC? how do I write `core.stdcpp.vector.vector` then?Ha, I saw vector.d there, So I can use this vector.d as the D side of C++'s std::vector?Probably, I just don't know how well tested it is. But worth a go!
Jun 18 2023
If I use array: ``` extern(C++) { void getInts(core.stdcpp.array.array!(int, 10) vec) { foreach (int i; 0 .. 10) { vec.at(i) = i; } } } ``` ``` #include <array> using namespace std; void getInts(array<int,10>* vector); ``` Both DMD and LDC has link error: base.cpp:42: undefined reference to `getInts(std::array<int, 10ul>*)'
Jun 18 2023