Jump to page: 1 2
Thread overview
Why can't we use strings in C++ methods?
Nov 04, 2023
Dadoum
Nov 04, 2023
Imperatorn
Nov 04, 2023
Dadoum
Nov 04, 2023
Johan
Nov 04, 2023
Dadoum
Nov 04, 2023
Dadoum
Nov 04, 2023
Dadoum
Nov 04, 2023
Basile B.
Nov 04, 2023
Imperatorn
Nov 04, 2023
Dadoum
Nov 04, 2023
Imperatorn
Nov 04, 2023
Dadoum
Nov 04, 2023
Paul Backus
Nov 04, 2023
Dadoum
November 04, 2023

I was wondering why C++ linkage forbids strings as arguments while we can with the C one.

With C linkage, it's translated to a template that's defined in the automatically generated header, but it just doesn't compile in C++.

November 04, 2023

On Saturday, 4 November 2023 at 03:00:49 UTC, Dadoum wrote:

>

I was wondering why C++ linkage forbids strings as arguments while we can with the C one.

With C linkage, it's translated to a template that's defined in the automatically generated header, but it just doesn't compile in C++.

Can you provide an example of exactly what you want to do?

November 04, 2023

On Saturday, 4 November 2023 at 10:08:20 UTC, Imperatorn wrote:

>

On Saturday, 4 November 2023 at 03:00:49 UTC, Dadoum wrote:

>

I was wondering why C++ linkage forbids strings as arguments while we can with the C one.

With C linkage, it's translated to a template that's defined in the automatically generated header, but it just doesn't compile in C++.

Can you provide an example of exactly what you want to do?

extern (C) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Compiles fine with dmd, ldc2 and gdc.

extern (C++) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Doesn't compile.

DMD: Internal Compiler Error: type string cannot be mapped to C++
GDC and LDC2: function 'example.hello' cannot have parameter of type 'string' because its linkage is 'extern(C++)'

And I am wondering why the type can be mapped to a template in C but not in C++. (you can see the template used when you compile with -H --HCf=./header.h

November 04, 2023

On Saturday, 4 November 2023 at 11:18:02 UTC, Dadoum wrote:

>

On Saturday, 4 November 2023 at 10:08:20 UTC, Imperatorn wrote:

>

On Saturday, 4 November 2023 at 03:00:49 UTC, Dadoum wrote:

>

I was wondering why C++ linkage forbids strings as arguments while we can with the C one.

With C linkage, it's translated to a template that's defined in the automatically generated header, but it just doesn't compile in C++.

Can you provide an example of exactly what you want to do?

extern (C) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Compiles fine with dmd, ldc2 and gdc.

extern (C++) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Doesn't compile.

DMD: Internal Compiler Error: type string cannot be mapped to C++
GDC and LDC2: function 'example.hello' cannot have parameter of type 'string' because its linkage is 'extern(C++)'

And I am wondering why the type can be mapped to a template in C but not in C++. (you can see the template used when you compile with -H --HCf=./header.h

So C-strings are just an array of characters that are governed by simple functions and D strings also defined the same. So you could see that D strings are possibly built on the architecture of C strings. In C++, string is a complex standard template library that generates complex symbols and cannot be mapped as it is based on a standard library implementation.

November 04, 2023

On Saturday, 4 November 2023 at 11:18:02 UTC, Dadoum wrote:

>

On Saturday, 4 November 2023 at 10:08:20 UTC, Imperatorn wrote:

>

On Saturday, 4 November 2023 at 03:00:49 UTC, Dadoum wrote:

>

I was wondering why C++ linkage forbids strings as arguments while we can with the C one.

With C linkage, it's translated to a template that's defined in the automatically generated header, but it just doesn't compile in C++.

Can you provide an example of exactly what you want to do?

extern (C) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Compiles fine with dmd, ldc2 and gdc.

extern (C++) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Doesn't compile.

DMD: Internal Compiler Error: type string cannot be mapped to C++
GDC and LDC2: function 'example.hello' cannot have parameter of type 'string' because its linkage is 'extern(C++)'

And I am wondering why the type can be mapped to a template in C but not in C++. (you can see the template used when you compile with -H --HCf=./header.h

We can just assume what you're doing on the C++-side. Are you using std::string?

You could try as a pointer + length and it might work, but without seeing your complete code it's quite hard to know what you want to do.

November 04, 2023

On Saturday, 4 November 2023 at 12:01:11 UTC, Emmanuel Danso Nyarko wrote:

>

On Saturday, 4 November 2023 at 11:18:02 UTC, Dadoum wrote:

>
extern (C) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Compiles fine with dmd, ldc2 and gdc.

extern (C++) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Doesn't compile.

DMD: Internal Compiler Error: type string cannot be mapped to C++
GDC and LDC2: function 'example.hello' cannot have parameter of type 'string' because its linkage is 'extern(C++)'

And I am wondering why the type can be mapped to a template in C but not in C++. (you can see the template used when you compile with -H --HCf=./header.h

So C-strings are just an array of characters that are governed by simple functions and D strings also defined the same.

This is not true. D string (=slice) variables store the length of the string in addition to the reference to the array of characters.

The reason this "works" with extern (C) is because the C mangling of a function name does not include the type of the parameters. Note that C does not have a string type, so to call the function from C you will have to write a different function signature in C (you'll see that char[] will not work).

It does not work with extern(C++) because the C++ mangling of a function does include the type of the parameters, and there is no built-in C++ type that is equivalent to D's string.

-Johan

November 04, 2023

On Saturday, 4 November 2023 at 12:21:45 UTC, Johan wrote:

>

On Saturday, 4 November 2023 at 12:01:11 UTC, Emmanuel Danso Nyarko wrote:

>

On Saturday, 4 November 2023 at 11:18:02 UTC, Dadoum wrote:

>
extern (C) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Compiles fine with dmd, ldc2 and gdc.

extern (C++) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Doesn't compile.

DMD: Internal Compiler Error: type string cannot be mapped to C++
GDC and LDC2: function 'example.hello' cannot have parameter of type 'string' because its linkage is 'extern(C++)'

And I am wondering why the type can be mapped to a template in C but not in C++. (you can see the template used when you compile with -H --HCf=./header.h

So C-strings are just an array of characters that are governed by simple functions and D strings also defined the same.

This is not true. D string (=slice) variables store the length of the string in addition to the reference to the array of characters.

The reason this "works" with extern (C) is because the C mangling of a function name does not include the type of the parameters. Note that C does not have a string type, so to call the function from C you will have to write a different function signature in C (you'll see that char[] will not work).

It does not work with extern(C++) because the C++ mangling of a function does include the type of the parameters, and there is no built-in C++ type that is equivalent to D's string.

-Johan

What I don't understand is why it cannot use the template it defines in the header.

Here it is:

// Automatically generated by LDC Compiler

#pragma once

#include <assert.h>
#include <math.h>
#include <stddef.h>
#include <stdint.h>

#ifdef CUSTOM_D_ARRAY_TYPE
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
#else
/// Represents a D [] array
template<typename T>
struct _d_dynamicArray final
{
    size_t length;
    T *ptr;

    _d_dynamicArray() : length(0), ptr(NULL) { }

    _d_dynamicArray(size_t length_in, T *ptr_in)
        : length(length_in), ptr(ptr_in) { }

    T& operator[](const size_t idx) {
        assert(idx < length);
        return ptr[idx];
    }

    const T& operator[](const size_t idx) const {
        assert(idx < length);
        return ptr[idx];
    }
};
#endif

extern "C" void hello(_d_dynamicArray< const char > arg);

And the D compiler can generate templates in the mangled name, as this D code is translated to C++:

class Foo(T) {}

extern (C++) void hello2(Foo!char arg2) {

}
// Automatically generated by LDC Compiler

#pragma once

#include <assert.h>
#include <math.h>
#include <stddef.h>
#include <stdint.h>

#ifdef CUSTOM_D_ARRAY_TYPE
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
#else
/// Represents a D [] array
template<typename T>
struct _d_dynamicArray final
{
    size_t length;
    T *ptr;

    _d_dynamicArray() : length(0), ptr(NULL) { }

    _d_dynamicArray(size_t length_in, T *ptr_in)
        : length(length_in), ptr(ptr_in) { }

    T& operator[](const size_t idx) {
        assert(idx < length);
        return ptr[idx];
    }

    const T& operator[](const size_t idx) const {
        assert(idx < length);
        return ptr[idx];
    }
};
#endif

template <typename T>
class Foo;

extern void hello2(Foo<char >* arg2);
November 04, 2023

On Saturday, 4 November 2023 at 12:07:12 UTC, Imperatorn wrote:

>

[...]

We can just assume what you're doing on the C++-side. Are you using std::string?

You could try as a pointer + length and it might work, but without seeing your complete code it's quite hard to know what you want to do.

I will use whatever D gives me in the C++ header, because in fact I am using Swift on the other side, so using std::string isn't useful. I already made a conversion function from Swift strings to D strings when they are represented with C linkage.

November 04, 2023

On Saturday, 4 November 2023 at 12:01:11 UTC, Emmanuel Danso Nyarko wrote:

>

[...]

So C-strings are just an array of characters that are governed by simple functions and D strings also defined the same. So you could see that D strings are possibly built on the architecture of C strings. In C++, string is a complex standard template library that generates complex symbols and cannot be mapped as it is based on a standard library implementation.

I don't think the strings are being translated in any way when we change the linkage. Strings in D are dynamic arrays of chars, the C binding code is giving us a template representing D's dynamic arrays, and so I thought that we could also use it in C++ for interoperability with D dynamic arrays.

November 04, 2023

On Saturday, 4 November 2023 at 12:21:45 UTC, Johan wrote:

>

On Saturday, 4 November 2023 at 12:01:11 UTC, Emmanuel Danso Nyarko wrote:

>

On Saturday, 4 November 2023 at 11:18:02 UTC, Dadoum wrote:

>
extern (C) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Compiles fine with dmd, ldc2 and gdc.

extern (C++) void hello(string arg) {
    import std.stdio;
    writeln(arg);
}

Doesn't compile.

DMD: Internal Compiler Error: type string cannot be mapped to C++
GDC and LDC2: function 'example.hello' cannot have parameter of type 'string' because its linkage is 'extern(C++)'

And I am wondering why the type can be mapped to a template in C but not in C++. (you can see the template used when you compile with -H --HCf=./header.h

So C-strings are just an array of characters that are governed by simple functions and D strings also defined the same.

This is not true. D string (=slice) variables store the length of the string in addition to the reference to the array of characters.

The reason this "works" with extern (C) is because the C mangling of a function name does not include the type of the parameters. Note that C does not have a string type, so to call the function from C you will have to write a different function signature in C (you'll see that char[] will not work).

It does not work with extern(C++) because the C++ mangling of a function does include the type of the parameters, and there is no built-in C++ type that is equivalent to D's string.

-Johan

You're right but that's not what he's looking for I think. He wants to understand why it doesn't compile at all. One major cause of failed compilation is syntax disagreements And my main point is that because C++ doesn't know independent 'string' and that the string in C++ is a standard template library, the D compiler decides to stop any symbol generated interaction with string because C++ syntatically doesn't know 'string'.

Maybe the compiler team could provide a better answer to him but that's what I think.

« First   ‹ Prev
1 2