Thread overview
Bind C++ class to DLang : undefined reference to `Canvas::Foo()'
Jul 12, 2020
zoujiaqing
Jul 13, 2020
zoujiaqing
Jul 13, 2020
Adam D. Ruppe
Jul 13, 2020
zoujiaqing
Jul 14, 2020
Boris Carvajal
Jul 15, 2020
Jacob Carlborg
Jul 14, 2020
evilrat
July 12, 2020
/// Canvas.hpp

#include <iostream>;

class Canvas
{
    static Canvas* Create();

    std::string Foo();

    std::string Bar();
};



/// Canvas.cpp

#include "Canvas.hpp"

#include <iostream>

Canvas* Canvas::Create()
{
    return new Canvas();
}

std::string Canvas::Foo()
{
    return "Foo";
}

std::string Canvas::Bar()
{
    return "Bar";
}



/// main.d

import std.stdio;

extern(C++)
{
    class Canvas
    {
        @disable this();

        static Canvas Create();

        string Foo();

        string Bar();
    };
}

void main()
{
	Canvas canvas = Canvas.Create();

	writeln(canvas.Foo());

	writeln(canvas.Bar());
}



# clang++ -I./include/ -fPIE -c src/Canvas.cpp
# dmd source/main.d Canvas.o -L-lstdc++ && ./main
/usr/bin/ld: main.o:(.data._D4main6Canvas6__vtblZ+0x0): undefined reference to `Canvas::Foo()'
/usr/bin/ld: main.o:(.data._D4main6Canvas6__vtblZ+0x8): undefined reference to `Canvas::Bar()'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1



July 13, 2020
I changed string to basic_string.

///  source/main.d
import std.stdio;
import core.stdcpp.string;

extern(C++)
{
    class Canvas
    {
        @disable this();

        static Canvas Create();

        basic_string!ubyte Foo();

        basic_string!ubyte Bar();
    };
}

void main()
{
	Canvas canvas = Canvas.Create();

	writeln(canvas.Foo());

	writeln(canvas.Bar());
}

Error ...

# dmd source/main.d Canvas.o -L-lstdc++ && ./main
[1]    49078 segmentation fault  ./main

July 13, 2020
On Monday, 13 July 2020 at 09:34:35 UTC, zoujiaqing wrote:
> # dmd source/main.d Canvas.o -L-lstdc++ && ./main
> [1]    49078 segmentation fault  ./main

On my computer I got this warning out of the compiler:

libstdc++ std::__cxx11::basic_string is not yet supported; the struct contains an interior pointer which breaks D move semantics!


sounds like it might be a known limitation.
July 13, 2020
On Monday, 13 July 2020 at 12:57:52 UTC, Adam D. Ruppe wrote:
> On Monday, 13 July 2020 at 09:34:35 UTC, zoujiaqing wrote:
>> # dmd source/main.d Canvas.o -L-lstdc++ && ./main
>> [1]    49078 segmentation fault  ./main
>
> On my computer I got this warning out of the compiler:
>
> libstdc++ std::__cxx11::basic_string is not yet supported; the struct contains an interior pointer which breaks D move semantics!
>
>
> sounds like it might be a known limitation.

Thanks Adam, but D link to C++ very hard?
July 14, 2020
On Monday, 13 July 2020 at 09:34:35 UTC, zoujiaqing wrote:
> I changed string to basic_string.
>
> ///  source/main.d
> import std.stdio;
> import core.stdcpp.string;
>
> extern(C++)
> {
>     class Canvas
>     {
>         @disable this();
>
>         static Canvas Create();
>
>         basic_string!ubyte Foo();
>
>         basic_string!ubyte Bar();
>     };
> }
>
> void main()
> {
> 	Canvas canvas = Canvas.Create();
>
> 	writeln(canvas.Foo());
>
> 	writeln(canvas.Bar());
> }
>
> Error ...
>
> # dmd source/main.d Canvas.o -L-lstdc++ && ./main
> [1]    49078 segmentation fault  ./main

Putting std::string support aside there is another issue in this example. D has virtual by default semantic unlike C++.

One possible segfault reason is that because it tries to call non existing virtual method.

Marking those D methods 'final' should fix linking issues. Also I can't remember if extern(C++) is implicitly propagated to class methods so I would put extern(C++) in class body just to be sure.

July 14, 2020
On Monday, 13 July 2020 at 16:17:55 UTC, zoujiaqing wrote:
> On Monday, 13 July 2020 at 12:57:52 UTC, Adam D. Ruppe wrote:
>> On Monday, 13 July 2020 at 09:34:35 UTC, zoujiaqing wrote:
>>> # dmd source/main.d Canvas.o -L-lstdc++ && ./main
>>> [1]    49078 segmentation fault  ./main
>>
>> On my computer I got this warning out of the compiler:
>>
>> libstdc++ std::__cxx11::basic_string is not yet supported; the struct contains an interior pointer which breaks D move semantics!
>>
>>
>> sounds like it might be a known limitation.
>
> Thanks Adam, but D link to C++ very hard?

Can you try passing -D_GLIBCXX_USE_CXX11_ABI=0 to g++ and -version=_GLIBCXX_USE_CXX98_ABI to dmd.

That comes from: https://dlang.org/changelog/2.088.0.html#std_string

C++11 ABI is currently not supported.
July 15, 2020
On 2020-07-14 05:33, Boris Carvajal wrote:

> Can you try passing -D_GLIBCXX_USE_CXX11_ABI=0 to g++ and -version=_GLIBCXX_USE_CXX98_ABI to dmd.
> 
> That comes from: https://dlang.org/changelog/2.088.0.html#std_string
> 
> C++11 ABI is currently not supported.

I based on previous messages and the usage of Clang, I think zoujiaqing is using a Mac. On Mac libc++ is used. That above might not apply.

-- 
/Jacob Carlborg