Jump to page: 1 2
Thread overview
D and C++ undefined reference when namespace
Mar 08, 2018
Markus
Mar 08, 2018
Markus
Mar 08, 2018
Markus
Mar 09, 2018
Markus
Mar 08, 2018
kinke
Mar 08, 2018
Markus
March 08, 2018
Hi

I got the following c++ code [lib.cpp]:
namespace ns_a
{
  class class_a {
  };
  void some_function(class_a*) {;}
}

and the following d code [main.d]:
extern (C++, namespace_a) {
    class class_a {}
    void some_function(class_a);
}
void main() {
    namespace_a.class_a instance_a;
    namespace_a.some_function(instance_a);
}

I'm compiling lib.cpp to a shared library by:
g++ -shared lib.cpp -o libissue.so
and I'm building and linking it with main.d by
dmd main.d -L-lissue -L-L.

Then I get the error:
main.o: In function `_Dmain':
main.d:(.text._Dmain[_Dmain]+0xa): undefined reference to `namespace_a::some_function(namespace_a::class_a*)'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1

When I move the c++ class_a to another namespace (eg. to namespace_b), I'm able to compile and link!
readelf -Ws libissue.so | grep some_function
gives me
_ZN4ns_a13some_functionEPNS_7class_aE
so I don't see any issue. Any idea what I'm missing? I guess some linker flag when compiling libissue.so

Cheers,
Markus
March 08, 2018
On 3/8/18 10:27 AM, Markus wrote:
> Hi
> 
> I got the following c++ code [lib.cpp]:
> namespace ns_a
> {
>    class class_a {
>    };
>    void some_function(class_a*) {;}
> }
> 
> and the following d code [main.d]:
> extern (C++, namespace_a) {

did you mean ns_a?

-Steve
March 08, 2018
On Thursday, 8 March 2018 at 15:27:31 UTC, Markus wrote:
> Hi
>
> I got the following c++ code [lib.cpp]:
> namespace ns_a
> {
>   class class_a {
>   };
>   void some_function(class_a*) {;}
> }
>
> and the following d code [main.d]:
> extern (C++, namespace_a) {
>     class class_a {}
>     void some_function(class_a);
> }
> void main() {
>     namespace_a.class_a instance_a;
>     namespace_a.some_function(instance_a);
> }
>
> I'm compiling lib.cpp to a shared library by:
> g++ -shared lib.cpp -o libissue.so
> and I'm building and linking it with main.d by
> dmd main.d -L-lissue -L-L.
>
> Then I get the error:
> main.o: In function `_Dmain':
> main.d:(.text._Dmain[_Dmain]+0xa): undefined reference to `namespace_a::some_function(namespace_a::class_a*)'
> collect2: error: ld returned 1 exit status
> Error: linker exited with status 1
>
> When I move the c++ class_a to another namespace (eg. to namespace_b), I'm able to compile and link!
> readelf -Ws libissue.so | grep some_function
> gives me
> _ZN4ns_a13some_functionEPNS_7class_aE
> so I don't see any issue. Any idea what I'm missing? I guess some linker flag when compiling libissue.so
>
> Cheers,
> Markus

https://forum.dlang.org/thread/mailman.2458.1448772039.22025.digitalmars-d@puremagic.com
seems to describe my issue.
To quote Walter Wright
> D does not support C++ semantics. You cannot split namespaces into multiple files in D, nor can you add symbols to an existing namespace. For namespace NS, all the declarations in NS have to be in one file and between the { }, just like any other scope in D.
in my opinion, that's really annoying for C++ wrapper devs.

I failed to describe my issue in the first post.
there has to be another.d
the function and class have to be in seperate d files.

Sorry for the spam
March 08, 2018
On Thursday, 8 March 2018 at 16:19:40 UTC, Steven Schveighoffer wrote:
> On 3/8/18 10:27 AM, Markus wrote:
>> Hi
>> 
>> I got the following c++ code [lib.cpp]:
>> namespace ns_a
>> {
>>    class class_a {
>>    };
>>    void some_function(class_a*) {;}
>> }
>> 
>> and the following d code [main.d]:
>> extern (C++, namespace_a) {
>
> did you mean ns_a?
>
> -Steve

yes, that's clearly the issue in my first post. :) I failed when I made a minimal sample for this forum

[lib.cpp]:
namespace ns_a
{
  class class_a {
  };
  void some_function(class_a*) {;}
}

[other.d]:
extern (C++, ns_a) {
    class class_a {}
}

[main.d]:
import other;
extern (C++, ns_a) {
    void some_function(class_a);
}
void main() {
    class_a instance_a;
    ns_a.some_function(instance_a);
}

compilation:
g++ -shared lib.cpp -o libissue.so
dmd main.d -L-lissue -L-L.

error:
main.o: In function `_Dmain':
main.d:(.text._Dmain[_Dmain]+0xa): undefined reference to `ns_a::some_function(ns_a::class_a*)'
collect2: error: ld returned 1 exit status
Error: linker exited with status 1

symbols:
nm --demangle libissue.so | some_function
000000000000059a T ns_a::some_function(ns_a::class_a*)

It doesn't seem like an error, but it is.
I still don't get it, whey I'm not allowed to split the namespace declarations.

March 08, 2018
On 3/8/18 11:23 AM, Markus wrote:
> On Thursday, 8 March 2018 at 15:27:31 UTC, Markus wrote:
>> Hi
>>
>> I got the following c++ code [lib.cpp]:
>> namespace ns_a
>> {
>>   class class_a {
>>   };
>>   void some_function(class_a*) {;}
>> }
>>
>> and the following d code [main.d]:
>> extern (C++, namespace_a) {
>>     class class_a {}
>>     void some_function(class_a);
>> }
>> void main() {
>>     namespace_a.class_a instance_a;
>>     namespace_a.some_function(instance_a);
>> }
>>
>> I'm compiling lib.cpp to a shared library by:
>> g++ -shared lib.cpp -o libissue.so
>> and I'm building and linking it with main.d by
>> dmd main.d -L-lissue -L-L.
>>
>> Then I get the error:
>> main.o: In function `_Dmain':
>> main.d:(.text._Dmain[_Dmain]+0xa): undefined reference to `namespace_a::some_function(namespace_a::class_a*)'
>> collect2: error: ld returned 1 exit status
>> Error: linker exited with status 1
>>
>> When I move the c++ class_a to another namespace (eg. to namespace_b), I'm able to compile and link!
>> readelf -Ws libissue.so | grep some_function
>> gives me
>> _ZN4ns_a13some_functionEPNS_7class_aE
>> so I don't see any issue. Any idea what I'm missing? I guess some linker flag when compiling libissue.so
>>
>> Cheers,
>> Markus
> 
> https://forum.dlang.org/thread/mailman.2458.1448772039.22025.digitalmars-d@puremagic.com 
> 
> seems to describe my issue.
> To quote Walter Wright
>> D does not support C++ semantics. You cannot split namespaces into multiple files in D, nor can you add symbols to an existing namespace. For namespace NS, all the declarations in NS have to be in one file and between the { }, just like any other scope in D.
> in my opinion, that's really annoying for C++ wrapper devs.

Hm... that is over 2 years old. I would agree it would seem like a bad limitation.

And the error message doesn't seem like a linker error, whereas yours does. If it gets to the linker, D hasn't complained about it.

-Steve
March 08, 2018
On 3/8/18 11:35 AM, Markus wrote:

> 
> error:
> main.o: In function `_Dmain':
> main.d:(.text._Dmain[_Dmain]+0xa): undefined reference to `ns_a::some_function(ns_a::class_a*)'
> collect2: error: ld returned 1 exit status
> Error: linker exited with status 1
> 
> symbols:
> nm --demangle libissue.so | some_function
> 000000000000059a T ns_a::some_function(ns_a::class_a*)
> 
> It doesn't seem like an error, but it is.
> I still don't get it, whey I'm not allowed to split the namespace declarations.
> 

This is a linker error. Your D code is compiling just fine (in other words, the aforementioned issue is not happening to you), it's just not getting the definition from the dynamic library.

When I do this locally on my mac, I get a similar error. When I nm the main.o file vs. the lib.o file, I see different mangled names.

It appears that the D mangled name is not doing back references. This is probably why the change to another namespace for the function works (there isn't a back reference)

In order to demonstrate this better, I did namespace thenamespace instead of ns_a.

The symbol I see in the D file:
U __ZN12thenamespace13some_functionEPN12thenamespace7class_aE

And in the C++ file:
T __ZN12thenamespace13some_functionEPNS_7class_aE

Note the difference is instead of 12thenamespace, it's S_, which probably is a back reference. Googled...

Yep, I'm right: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.seq-id

I'd recommend filing a bug.

-Steve
March 08, 2018
On Thursday, 8 March 2018 at 17:04:02 UTC, Steven Schveighoffer wrote:
> On 3/8/18 11:35 AM, Markus wrote:
> When I do this locally on my mac, I get a similar error. When I nm the main.o file vs. the lib.o file, I see different mangled names.
>
> It appears that the D mangled name is not doing back references. This is probably why the change to another namespace for the function works (there isn't a back reference)
>
> In order to demonstrate this better, I did namespace thenamespace instead of ns_a.
>
> The symbol I see in the D file:
> U __ZN12thenamespace13some_functionEPN12thenamespace7class_aE
>
> And in the C++ file:
> T __ZN12thenamespace13some_functionEPNS_7class_aE
>
> Note the difference is instead of 12thenamespace, it's S_, which probably is a back reference. Googled...
>
> Yep, I'm right: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.seq-id
>
> I'd recommend filing a bug.
>
> -Steve

You are right.
$ dmd -c main.d
$ nm main.o | grep some
                 U _ZN4ns_a13some_functionEPN4ns_a7class_aE
$ nm lib.o | grep some
0000000000000000 T _ZN4ns_a13some_functionEPNS_7class_aE

But when i merge the main.d and other.d I get
$ nm main.o | grep some
                 U _ZN4ns_a13some_functionEPNS_7class_aE

I tested dmd (2.079.0), gdc and ldc2. All got the same result. Which makes me think, that it's not a bug, but a "feature" :)
March 08, 2018
On 3/8/18 1:56 PM, Markus wrote:
> 
> You are right.
> $ dmd -c main.d
> $ nm main.o | grep some
>                   U _ZN4ns_a13some_functionEPN4ns_a7class_aE
> $ nm lib.o | grep some
> 0000000000000000 T _ZN4ns_a13some_functionEPNS_7class_aE
> 
> But when i merge the main.d and other.d I get
> $ nm main.o | grep some
>                   U _ZN4ns_a13some_functionEPNS_7class_aE
> 
> I tested dmd (2.079.0), gdc and ldc2. All got the same result. Which makes me think, that it's not a bug, but a "feature" :)

Ah interesting. What it looks like is that the symbol for the namespace is considered different between the two files in D-land, but they have the same name in C++-land. So it thinks it's not a back reference, but really it should be.

-Steve
March 08, 2018
On 3/8/18 1:56 PM, Markus wrote:
> I tested dmd (2.079.0), gdc and ldc2. All got the same result. Which makes me think, that it's not a bug, but a "feature" :)

This is DEFINITELY a bug.

-Steve
March 08, 2018
On Thursday, 8 March 2018 at 18:56:04 UTC, Markus wrote:
> I tested dmd (2.079.0), gdc and ldc2. All got the same result. Which makes me think, that it's not a bug, but a "feature" :)

C++ mangling is part of the DMD front-end shared by all 3 compilers, so no surprises there: https://github.com/dlang/dmd/blob/master/src/dmd/cppmangle.d
« First   ‹ Prev
1 2