On Thursday, 29 September 2022 at 12:49:06 UTC, Riccardo M wrote:
> On Thursday, 29 September 2022 at 11:13:15 UTC, Ogi wrote:
So it turns out that D's structs are a much better match for C++'s classes in this case. But why is this? Can you elaborate? It must have to do with the fact that D structs are passed by value?
In C++, class and struct are basically the same thing (AFAIK the only difference is that struct members are public by default). In D, they are two very different things: classes are reference types — structs are value types, classes support inheritance — structs only support alias this
, and so on.
When interfacing to C++, disregard the keyword and look at the implementation instead. If all its member functions are non-virtual, map it to struct. Otherwise map it to class. If it defines at least one pure virtual member function, map it to abstract class. If all its member functions are either pure virtual or non-virtual and it contains no fields, map it to interface. Sounds complicated? Well, that’s because C++ is complicated.
> However the 'add' function only links correctly if C++ has the function body defined outside of its class.
// C++
int MyClass::add(int asd) {
return field + asd;
}
If the function is defined inside its class, it is an undefined reference at link time. Once again I ask for clarifications and workarounds, if possible.
In C++, member functions defined inside its class are called inline member functions. In contrast to normal functions which must be defined once and only once in your program, inline functions must be defined in every translation unit that uses them. Let’s replicate your linking error in C++:
//c.h
class C {
public:
int foo() {
return 42;
}
void bar();
};
//c.cpp
#include "c.h"
void C::bar() { /* ... */ }
//main.cpp
#include <stdio.h>
//Let’s see what happens if we forget `C::foo` definition:
class C {
public:
int foo();
void bar();
};
int main() {
auto c = new C();
printf("%d\n", c->foo());
c->bar();
return 0;
}
$ clang++ -c c.cpp
$ clang++ -c main.cpp
$ clang++ main.o c.o
main.o : error LNK2019: unresolved external symbol "public: int __cdecl C::foo(void)" (?foo@C@@QEAAHXZ) referenced in function main
a.exe : fatal error LNK1120: 1 unresolved externals
clang++: error: linker command failed with exit code 1120 (use -v to see invocation)
Copying C::foo
definition to main.cpp
will fix this. Of course, we could just include c.h
.
Same goes for D. MyClass.add
must be defined in your D module.