How to interface to C++ from D correctly?

255 views Asked by At

I tried to inteface between C++ and D.

The problem is that I can't compile it. I used the code/command line on the website

> g++ -c foo.cpp
> dmd bar.d foo.o -L-lstdc++ && ./bar

and it didn't work: first of all the DMD compiler doesn't use .o files so i had to specify manually to create a .obj file then the linker threw an error because it didn't knew /lstdc++ so i configured the cpp libs manually.

Thats the point where i am now it throws an "Symbol not found" error and i don't know how to fix this, am i doing something wrong on compiling? or is it on the programming site?

here my compile commands:

PS C:\Users\kunde\Downloads\d-interface test> g++ -c -o test-cpp.obj test.cpp
PS C:\Users\kunde\Downloads\d-interface test> dmd -L"G:\GNUstep\lib\gcc\mingw32\4.6.1\libstdc++.dll.a" -L"G:\GNUstep\lib\gcc\mingw32\4.6.1\libstdc++.a" .\test-cpp.obj .\test.d
test.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""char __cdecl foo(int)" (?foo@@YADH@Z)" in Funktion "__Dmain".
test-cpp.exe : fatal error LNK1120: 1 nicht aufgelöste Externe
Error: linker exited with status 1120

and my code: test.d:

import std.stdio;

extern (C++) char foo(int i);

void main(string[] args)
{
    writefln("%c", foo(14));
}

test.cpp:

#include <iostream>

extern "C" {
    #include "test.h"
}

char foo(int i){
    std::cout << "got: ";
    return (char)bar(i);
}

and test.h:

#include <stdio.h>

int bar(int a){
    printf("returned %d", a*a);
    return a*a;
}

What am I doing wrong?

P.s.: im german so the errors may have to be translated

Edit: As sayd in the answers MSVC fixed the problem i changed "g++ -c -o test-cpp.obj test.cpp" to "cl test.cpp -c /EHsc"

1

There are 1 answers

0
Adam D. Ruppe On

C++ is a finicky beast - its name mangling details are implementation defined, so it varies by platform and compiler. dmd picks one it considers the main compiler on the system and copies it. On Linux, that's g++.... but on Windows, it is Microsoft C++, not g++.

So you have to use a matching compiler. On Windows, there is the gdc compiler - a D compiler built into gcc - but there's no binary builds for it available at this time. You'd have to compile it yourself with some config flags...

../gcc/configure --prefix=/mingw64 --host=x86_64-w64-mingw32 --build=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 --disable-bootstrap --disable-werror --disable-libssp --disable-libgomp --disable-libmudflap --disable-libquadmath --disable-libitm  --disable-libsanitizer --disable-libstdcxx-pch --with-arch=x86-64 --with-gnu-as --with-gnu-ld --with-gmp=/mingw64 --with-mpfr=/mingw64 --with-mpc=/mingw64 --with-isl=/mingw64 --with-native-system-header-dir=/mingw64/x86_64-w64-mingw32/include --libexecdir=/mingw64/lib --enable-languages=d --enable-libphobos --enable-shared --enable-static --disable-multilib

is what I used.

It is a bit of a pain. I've never actually tested the extern(C++) on gdc/Windows either.

So I'd suggest either using the MSVC compiler on the C++ together with dmd.... or probably better yet making the interface extern(C) instead. The C interface is far more compatible across things.

And the .o vs .obj thing is the same case - gcc uses .o, dmd and msvc use .obj (at least -m64 bit builds match, 32 bit is more complicated depending on version number)... so really using the same compiler family is going to get you best results.