www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Compiling a mixed D and C++ project?

reply Kyle De'Vir <kyle.devir mykolab.com> writes:
I have my C++ code with the necessary functions that are wrapped 
for C linkage, but I'm not sure how to compile the D and wrapped 
C++ code.
Sep 02
next sibling parent reply a11e99z <black80 bk.ru> writes:
On Monday, 2 September 2019 at 13:24:17 UTC, Kyle De'Vir wrote:
 I have my C++ code with the necessary functions that are 
 wrapped for C linkage, but I'm not sure how to compile the D 
 and wrapped C++ code.
https://dlang.org/spec/cpp_interface.html
Sep 02
parent reply Kyle De'Vir <kyle.devir mykolab.com> writes:
On Monday, 2 September 2019 at 13:32:40 UTC, a11e99z wrote:
 https://dlang.org/spec/cpp_interface.html
That doesn't help me, sadly: I compile the C++ object, but when attempting to compile with `dmd Main.d TestApplication.o -L-lstdc++`, I get this error: https://invent.kde.org/snippets/428
Sep 02
parent reply Exil <Exil gmall.com> writes:
On Monday, 2 September 2019 at 13:51:11 UTC, Kyle De'Vir wrote:
 On Monday, 2 September 2019 at 13:32:40 UTC, a11e99z wrote:
 https://dlang.org/spec/cpp_interface.html
That doesn't help me, sadly: I compile the C++ object, but when attempting to compile with `dmd Main.d TestApplication.o -L-lstdc++`, I get this error: https://invent.kde.org/snippets/428
You have to link to Qt's libs when you are compiling your D code. Otherwise it won't know where to find those functions.
Sep 02
parent reply Kyle De'Vir <kyle.devir mykolab.com> writes:
On Monday, 2 September 2019 at 14:04:44 UTC, Exil wrote:
 You have to link to Qt's libs when you are compiling your D 
 code. Otherwise it won't know where to find those functions.
Ah. Right. How could I forget. :P This helped silence the error: `gdc Main.d TestApplication.o -lstdc++ -lQt5Core -lQt5Widgets` Anyways, now I have other errors: https://invent.kde.org/snippets/429 `SetAppAtrributes` is properly wrapped, so I'm unsure about that. The other ones I'm not sure what to do about.
Sep 02
parent reply Gregor =?UTF-8?B?TcO8Y2ts?= <gregormueckl gmx.de> writes:
On Monday, 2 September 2019 at 14:20:32 UTC, Kyle De'Vir wrote:
 On Monday, 2 September 2019 at 14:04:44 UTC, Exil wrote:
 You have to link to Qt's libs when you are compiling your D 
 code. Otherwise it won't know where to find those functions.
Ah. Right. How could I forget. :P This helped silence the error: `gdc Main.d TestApplication.o -lstdc++ -lQt5Core -lQt5Widgets` Anyways, now I have other errors: https://invent.kde.org/snippets/429 `SetAppAtrributes` is properly wrapped, so I'm unsure about that. The other ones I'm not sure what to do about.
Do you compile in the moc-generated code for TestApplication? "undefined reference to vtable" is a stupid gcc quirk. It only emits the vtable for a C++ class under certain circumstances. I think it puts it in the object file for the source file that has the implementation of the first virtual method in the class definition. If TestApplication is derived from QObject and uses the Q_OBJECT macro, then this virtual method is one that is created by moc for signal/slot handling.
Sep 02
parent reply Kyle De'Vir <kyle.devir mykolab.com> writes:
On Monday, 2 September 2019 at 15:58:12 UTC, Gregor Mückl wrote:
 Do you compile in the moc-generated code for TestApplication?

 "undefined reference to vtable" is a stupid gcc quirk. It only 
 emits the vtable for a C++ class under certain circumstances. I 
 think it puts it in the object file for the source file that 
 has the implementation of the first virtual method in the class 
 definition.  If TestApplication is derived from QObject and 
 uses the Q_OBJECT macro, then this virtual method is one that 
 is created by moc for signal/slot handling.
I was fiddling around, and compiling in the moc-generated code fixed the vtable errors. It was still complaining about `SetAppAtrributes`. Removing the function allowed it compile, but then I just get a segfault when trying to run it, which I have no way of understanding how to begin debugging. :| I might just fall back to making the Qt the frontend, with the Dlang code the backend. Sounds less messy. :(
Sep 02
parent reply Gregor =?UTF-8?B?TcO8Y2ts?= <gregormueckl gmx.de> writes:
On Monday, 2 September 2019 at 16:37:57 UTC, Kyle De'Vir wrote:
 I was fiddling around, and compiling in the moc-generated code 
 fixed the vtable errors.

 It was still complaining about `SetAppAtrributes`. Removing the 
 function allowed it compile, but then I just get a segfault 
 when trying to run it, which I have no way of understanding how 
 to begin debugging. :|

 I might just fall back to making the Qt the frontend, with the 
 Dlang code the backend. Sounds less messy. :(
Can you show us the Declaration for SetAppAttributes in C++ and in D? I suspect a subtle mismatch.
Sep 02
parent reply Kyle De'Vir <kyle.devir mykolab.com> writes:
On Monday, 2 September 2019 at 16:48:41 UTC, Gregor Mückl wrote:
 Can you show us the Declaration for SetAppAttributes in C++ and 
 in D? I suspect a subtle mismatch.
Yeah, there was. I missed it multiple times, somehow. Doesn't resolve the segfaults, though, which I'm close to giving up on.
Sep 02
parent reply Eduard Staniloiu <edi33416 gmail.com> writes:
On Monday, 2 September 2019 at 17:36:20 UTC, Kyle De'Vir wrote:
 On Monday, 2 September 2019 at 16:48:41 UTC, Gregor Mückl wrote:
 Can you show us the Declaration for SetAppAttributes in C++ 
 and in D? I suspect a subtle mismatch.
Yeah, there was. I missed it multiple times, somehow. Doesn't resolve the segfaults, though, which I'm close to giving up on.
You could also try to compile the D code into an object and link with libdruntime and libphobos, using g++ or what C++ compiler you are using
Sep 02
parent reply Kyle De'Vir <kyle.devir mykolab.com> writes:
On Monday, 2 September 2019 at 18:00:04 UTC, Eduard Staniloiu 
wrote:
 You could also try to compile the D code into an object and 
 link with libdruntime and libphobos, using g++ or what C++ 
 compiler you are using
Thanks for the suggestion. Will give this a try.
Sep 02
parent reply Kyle De'Vir <kyle.devir mykolab.com> writes:
On Monday, 2 September 2019 at 18:01:20 UTC, Kyle De'Vir wrote:
 On Monday, 2 September 2019 at 18:00:04 UTC, Eduard Staniloiu 
 wrote:
 You could also try to compile the D code into an object and 
 link with libdruntime and libphobos, using g++ or what C++ 
 compiler you are using
Thanks for the suggestion. Will give this a try.
Yeah, made no difference. It compiles, but running yields a segfault.
Sep 02
parent reply Manu <turkeyman gmail.com> writes:
On Mon., 2 Sep. 2019, 11:10 am Kyle De'Vir via Digitalmars-d, <
digitalmars-d puremagic.com> wrote:

 On Monday, 2 September 2019 at 18:01:20 UTC, Kyle De'Vir wrote:
 On Monday, 2 September 2019 at 18:00:04 UTC, Eduard Staniloiu
 wrote:
 You could also try to compile the D code into an object and
 link with libdruntime and libphobos, using g++ or what C++
 compiler you are using
Thanks for the suggestion. Will give this a try.
Yeah, made no difference. It compiles, but running yields a segfault.
You'll need to give us more information... What is the segfault? Can you show the callstack? (Build the C++ and D code with debug info `-g`)

Sep 02
parent reply Kyle De'Vir <kyle.devir mykolab.com> writes:
On Monday, 2 September 2019 at 19:22:01 UTC, Manu wrote:
 You'll need to give us more information... What is the 
 segfault? Can you show the callstack? (Build the C++ and D code 
 with debug info `-g`)
I just get "Segmentation fault (core dumped)", but here's the callstack from coredumpctl: https://invent.kde.org/snippets/430
Sep 02
parent reply Kyle De'Vir <kyle.devir mykolab.com> writes:
Here is my code, by the way:

main.d
https://invent.kde.org/snippets/431

TestApplication.h
https://invent.kde.org/snippets/432

TestApplication.cpp
https://invent.kde.org/snippets/433
Sep 02
next sibling parent Kyle De'Vir <kyle.devir mykolab.com> writes:
Also, the build command:

gdc \
     -g \
     -lstdc++ \
     -lQt5Core \
     -lQt5Widgets \
     -fPIC \
     -Ibuild/TestApplication_autogen/include \
     -isystem /usr/include/qt \
     -isystem /usr/include/qt/QtWidgets \
     -isystem /usr/include/qt/QtGui \
     -isystem /usr/include/qt/QtCore \
     -isystem /usr/lib/qt/mkspecs/linux-g++ \
     -o AppD \
     Sources/TestApplication.cpp Sources/Main.d 
build/TestApplication_autogen/mocs_compilation.cpp
Sep 02
prev sibling parent reply Manu <turkeyman gmail.com> writes:
On Mon, Sep 2, 2019 at 12:55 PM Kyle De'Vir via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 Here is my code, by the way:

 main.d
 https://invent.kde.org/snippets/431

 TestApplication.h
 https://invent.kde.org/snippets/432

 TestApplication.cpp
 https://invent.kde.org/snippets/433
It looks like you're mixing up C++ classes and D structs, which are completely different. You shouldn't use extern(C), you should use extern(C++), and then you'll get proper errors when you fail to get the types correct, otherwise you'll continue to get surprising crashes like this when you match the types wrong. My guess is that maybe the problem starts here: extern __gshared struct QtApplication; QtApplication* TestApplication_Init(); QtApplication is a class with a vtable, so it should be `extern(C++) class` and definitely not `struct`. In D, classes are reference types, so you don't use '*' as in `QtApplication*` with classes, just `QtApplication`. Also, that's just a weird line; what does it mean? I haven't seen an `extern __gshared` struct before... but I think you mean: extern(C++) class QtApplication; QtApplication TestApplication_Init();
Sep 02
next sibling parent reply Kyle De'Vir <kyle.devir mykolab.com> writes:
Supposedly, C++ classes are the same as C structs, or something, 
and could be interchanged when mixing C / C++ code.

Would an opaque pointer work, perhaps...
Sep 02
parent reply Manu <turkeyman gmail.com> writes:
On Mon, Sep 2, 2019 at 11:15 PM Kyle De'Vir via Digitalmars-d
<digitalmars-d puremagic.com> wrote:
 Supposedly, C++ classes are the same as C structs, or something,
 and could be interchanged when mixing C / C++ code.

 Would an opaque pointer work, perhaps...
C++ classes or structs with vtables are the same as D classes. C++ classes or structs without vtables are the same as D struct. In this case, you should be using a D `extern(C++) class` so that it matches the C++ code. If you try exactly what I wrote, it might work better. And you should use extern(C++) everywhere instead of extern(C), otherwise you won't know when you've made mistakes that cause segfaults. C declarations don't carry argument types, to extern(C) can't tell you when functions don't match.
Sep 03
parent Kyle De'Vir <kyle.devir mykolab.com> writes:
On Tuesday, 3 September 2019 at 07:49:44 UTC, Manu wrote:
 C++ classes or structs with vtables are the same as D classes. 
 C++
 classes or structs without vtables are the same as D struct.
 In this case, you should be using a D `extern(C++) class` so 
 that it
 matches the C++ code.
 If you try exactly what I wrote, it might work better.

 And you should use extern(C++) everywhere instead of extern(C),
 otherwise you won't know when you've made mistakes that cause
 segfaults. C declarations don't carry argument types, to 
 extern(C)
 can't tell you when functions don't match.
Thanks for the advice. I'll give it a shot, then. I was avoiding using extern C++ because I was unsure about the status of Dlang's C++ interoperability, given how silly C++'s ABI incompatibilities can be.
Sep 03
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2019-09-02 22:29, Manu wrote:

 It looks like you're mixing up C++ classes and D structs, which are
 completely different.
 You shouldn't use extern(C), you should use extern(C++), and then
 you'll get proper errors when you fail to get the types correct,
 otherwise you'll continue to get surprising crashes like this when you
 match the types wrong.
 
 My guess is that maybe the problem starts here:
 
      extern __gshared struct QtApplication;
      QtApplication* TestApplication_Init();
 
 QtApplication is a class with a vtable, so it should be `extern(C++)
 class` and definitely not `struct`.
 In D, classes are reference types, so you don't use '*' as in
 `QtApplication*` with classes, just `QtApplication`.
No, not necessarily. He has created C wrappers around the C++ code and is treating the C++ class as an opaque pointer. Have a look here [1].
 Also, that's just a weird line; what does it mean? I haven't seen an
 `extern __gshared` struct before... but I think you mean:
    extern(C++) class QtApplication;
    QtApplication TestApplication_Init();
 
I think the actual problem is lines 32-35. The arguments to main are casted to a pointer to a D array, that won't work. It needs to be a C array, i.e. a pointer to a point of char. You can access the arguments to main as a C array from here [2]. [1] https://invent.kde.org/snippets/433 [2] https://dlang.org/phobos/core_runtime.html#.CArgs -- /Jacob Carlborg
Sep 03
parent Kyle De'Vir <kyle.devir mykolab.com> writes:
On Tuesday, 3 September 2019 at 08:57:56 UTC, Jacob Carlborg 
wrote:
 No, not necessarily. He has created C wrappers around the C++ 
 code and is treating the C++ class as an opaque pointer. Have a 
 look here [1].

 Also, that's just a weird line; what does it mean? I haven't 
 seen an
 `extern __gshared` struct before... but I think you mean:
    extern(C++) class QtApplication;
    QtApplication TestApplication_Init();
 
I think the actual problem is lines 32-35. The arguments to main are casted to a pointer to a D array, that won't work. It needs to be a C array, i.e. a pointer to a point of char. You can access the arguments to main as a C array from here [2]. [1] https://invent.kde.org/snippets/433 [2] https://dlang.org/phobos/core_runtime.html#.CArgs
This worked! Thank you! :)
Sep 03
prev sibling parent Exil <Exil gmall.com> writes:
On Monday, 2 September 2019 at 13:24:17 UTC, Kyle De'Vir wrote:
 I have my C++ code with the necessary functions that are 
 wrapped for C linkage, but I'm not sure how to compile the D 
 and wrapped C++ code.
Depending on what you are doing and how you want to do it. You would compile one or the other as either a static library or a shared library, then link to that when you compile the executable.
Sep 02