Thread overview
Calling C++ code with pointer** argument
Jun 01, 2016
abad
Jun 01, 2016
Mike Parker
Jun 01, 2016
Mike Parker
Jun 01, 2016
abad
Jun 01, 2016
Kagamin
Jun 01, 2016
Jesse Phillips
June 01, 2016
D source:

extern(C++) void thisWorks(const char* test);
extern(C++) void doesNotLink(const char** test);

void main() {
    char* baz1;
    char** baz2;
    thisWorks(baz1);
    doesNotLink(baz2);
}

CPP source:

#include <stdio.h>

void thisWorks(const char* test) {
    printf("hi\n");
}

void DoesNotLink(const char** test) {
    // not reached
}

The error given by the linker:
test.d:(.text._Dmain+0x21): undefined reference to `doesNotLink(char const* const*)'

What's happening? I know there are differences in const behavior between D and C++, but can't figure a way around it. Any sort of casting trick I tried doesn't seem to help.

June 01, 2016
On Wednesday, 1 June 2016 at 07:09:16 UTC, abad wrote:
> D source:
>
> extern(C++) void thisWorks(const char* test);
> extern(C++) void doesNotLink(const char** test);
>
> void main() {
>     char* baz1;
>     char** baz2;
>     thisWorks(baz1);
>     doesNotLink(baz2);
> }
>
> CPP source:
>
> #include <stdio.h>
>
> void thisWorks(const char* test) {
>     printf("hi\n");
> }
>
> void DoesNotLink(const char** test) {
>     // not reached
> }
>
> The error given by the linker:
> test.d:(.text._Dmain+0x21): undefined reference to `doesNotLink(char const* const*)'
>
> What's happening? I know there are differences in const behavior between D and C++, but can't figure a way around it. Any sort of casting trick I tried doesn't seem to help.

Try this:

extern(C++) void DoesNotLink(const(char)**);


June 01, 2016
On Wednesday, 1 June 2016 at 07:17:04 UTC, Mike Parker wrote:
> On Wednesday, 1 June 2016 at 07:09:16 UTC, abad wrote:

>>
>> What's happening? I know there are differences in const behavior between D and C++, but can't figure a way around it. Any sort of casting trick I tried doesn't seem to help.
>
> Try this:
>
> extern(C++) void DoesNotLink(const(char)**);

And I don't know if this was just a typo in your post,  but also note that you 'D'oesNotLink in the CPP source you pasted and 'd'oesNotLink in the D code.
June 01, 2016
On Wednesday, 1 June 2016 at 07:17:04 UTC, Mike Parker wrote:
> On Wednesday, 1 June 2016 at 07:09:16 UTC, abad wrote:
>
> Try this:
>
> extern(C++) void DoesNotLink(const(char)**);

That does work, though I have to explicitly cast it in my caller as well.
Like this:

doesNotLink(cast(const(char)**)baz2);

It's a bit troublesome as my code will include quite a lot of calls like this.

Casting is not necessary with the method call with the single pointer argument, as it seems to get const'ed automatically.

> And I don't know if this was just a typo in your post,  but also note that you 'D'oesNotLink in the CPP source you pasted and 'd'oesNotLink in the D code.

That was just a typo.

June 01, 2016
On Wednesday, 1 June 2016 at 07:29:56 UTC, abad wrote:
> That does work, though I have to explicitly cast it in my caller as well.
> Like this:
>
> doesNotLink(cast(const(char)**)baz2);
>
> It's a bit troublesome as my code will include quite a lot of calls like this.
>
> Casting is not necessary with the method call with the single pointer argument, as it seems to get const'ed automatically.

Can you declare it as const char*const* one the C++ side?
June 01, 2016
On Wednesday, 1 June 2016 at 16:16:26 UTC, Kagamin wrote:
> Can you declare it as const char*const* one the C++ side?

Just to state the problem clearly, D's const is transitive, C++ it is not. C linkage doesn't care about const, so you can specify it however you want. In C++ the const is included in the mangling, so it must match the declaration between C++ and D.

Transitive meaning that const will apply to all elements pointed to. This is why you see linker complain about not being able to find char const * const *