November 04

On Saturday, 4 November 2023 at 12:34:28 UTC, Dadoum wrote:

>

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.

There is a syntax disagreement here that's why the D compiler is instantly stopping you from doing any symbol generated interaction with string in C++ interop. C++ doesn't know 'string' and C++ mangles with parameters and so passing string will make string get involved with the symbol generation and since string(std::string) in C++ is a template library, the D compiler stops you from engaging with 'string'

November 04

On Saturday, 4 November 2023 at 13:45:56 UTC, Emmanuel Danso Nyarko wrote:

>

[...]

There is a syntax disagreement here that's why the D compiler is instantly stopping you from doing any symbol generated interaction with string in C++ interop. C++ doesn't know 'string' and C++ mangles with parameters and so passing string will make string get involved with the symbol generation and since string(std::string) in C++ is a template library, the D compiler stops you from engaging with 'string'

I don't think it's related to the existence of std::string at all since all dynamic array types are forbidden.

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

also fails to compile while this works:

extern (C) void hello(ubyte[] arg) {
        import std.stdio;
        writeln(arg);
}
November 04

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++.

extern(C++) functions use C++ name mangling, which includes the types of the parameters in the mangled name. However, since C++ does not have a built-in slice type like D's T[], there is no valid C++ mangling for a D slice. Because of this, it is impossible to compile an extern(C++) function that has a D slice as a parameter.

As a workaround, you can convert the slice to a struct:

struct DSlice(T)
{
    T* ptr;
    size_t length;

    T[] opIndex() => ptr[0 .. length];
}

DSlice!T toDslice(T)(T[] slice)
{
	return DSlice!T(slice.ptr, slice.length);
}

extern(C++) void hello(DSlice!(const(char)) arg)
{
    import std.stdio;
    writeln(arg[]);
}

void main()
{
	const(char)[] greeting = "hello";
	hello(greeting.toDslice);
}
November 04

On Saturday, 4 November 2023 at 13:51:20 UTC, Dadoum wrote:

>

On Saturday, 4 November 2023 at 13:45:56 UTC, Emmanuel Danso Nyarko wrote:

>

[...]

There is a syntax disagreement here that's why the D compiler is instantly stopping you from doing any symbol generated interaction with string in C++ interop. C++ doesn't know 'string' and C++ mangles with parameters and so passing string will make string get involved with the symbol generation and since string(std::string) in C++ is a template library, the D compiler stops you from engaging with 'string'

I don't think it's related to the existence of std::string at all since all dynamic array types are forbidden.

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

also fails to compile while this works:

extern (C) void hello(ubyte[] arg) {
        import std.stdio;
        writeln(arg);
}

Here too you will get the same error, cannot be mapped to C++. C++ mangles dynamic arrays as pointer arrays(uses the 'P' symbol), which is supported by D for interfacing with C. Another disagreement here using it in c++ interop. Hence will not compile. Once again, I think the compiler team will be the best to give you what you're looking for.

November 04

On Saturday, 4 November 2023 at 14:21:49 UTC, Paul Backus wrote:

>

[...]

extern(C++) functions use C++ name mangling, which includes the types of the parameters in the mangled name. However, since C++ does not have a built-in slice type like D's T[], there is no valid C++ mangling for a D slice. Because of this, it is impossible to compile an extern(C++) function that has a D slice as a parameter.

As a workaround, you can convert the slice to a struct:

[...]

I use another workaround myself:

extern (C++) struct List(T) { // or extern (C)
        T[] self;
        alias self this;
}

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

but it means adding a lot of edge cases to the mixins I use for bindings while showing that C++ can express D arrays.

(translated to

template <typename T>
struct List final
{
    _d_dynamicArray< T > self;
    List()
    {
    }
};

extern void hello(List<uint8_t > arg);

)

November 04

On Saturday, 4 November 2023 at 13:51:20 UTC, Dadoum wrote:

>

On Saturday, 4 November 2023 at 13:45:56 UTC, Emmanuel Danso Nyarko wrote:

>

[...]

There is a syntax disagreement here that's why the D compiler is instantly stopping you from doing any symbol generated interaction with string in C++ interop. C++ doesn't know 'string' and C++ mangles with parameters and so passing string will make string get involved with the symbol generation and since string(std::string) in C++ is a template library, the D compiler stops you from engaging with 'string'

I don't think it's related to the existence of std::string at all since all dynamic array types are forbidden.

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

also fails to compile while this works:

extern (C) void hello(ubyte[] arg) {
        import std.stdio;
        writeln(arg);
}

The type simply cannot be mangled using the C++ mangler as it does not exist over there. You might have the impression that this should be allowed, e.g as an extension, but keep in mind that extern(C++) is firstly designed to link against object produced by a C++ compiler.

Now why this works in extern(C) ? Because C does not mangle the parameters, a function linkage name is simply its unqualified name, so linking will work even if the parameter types are specific to D.

Now there is still the question whether the extern(C) code will work as expected or not.

November 04

On Saturday, 4 November 2023 at 14:33:56 UTC, Basile B. wrote:

>

On Saturday, 4 November 2023 at 13:51:20 UTC, Dadoum wrote:

>

[...]

The type simply cannot be mangled using the C++ mangler as it does not exist over there. You might have the impression that this should be allowed, e.g as an extension, but keep in mind that extern(C++) is firstly designed to link against object produced by a C++ compiler.

Now why this works in extern(C) ? Because C does not mangle the parameters, a function linkage name is simply its unqualified name, so linking will work even if the parameter types are specific to D.

Now there is still the question whether the extern(C) code will work as expected or not.

Could the mangling be provided with pragma and made to work?

November 04

On Saturday, 4 November 2023 at 14:21:49 UTC, Paul Backus wrote:

>

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

>

[...]

extern(C++) functions use C++ name mangling, which includes the types of the parameters in the mangled name. However, since C++ does not have a built-in slice type like D's T[], there is no valid C++ mangling for a D slice. Because of this, it is impossible to compile an extern(C++) function that has a D slice as a parameter.

[...]

Simply add perfectly explained!

November 04

On Saturday, 4 November 2023 at 14:33:56 UTC, Basile B. wrote:

>

[...]
Now there is still the question whether the extern(C) code will work as expected or not.

So with few patches could we make it work? DMD can write the C++ function prototype (as it does it with extern (C)) and then mangle it as the template it uses in C?

1 2
Next ›   Last »