Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Dadoum via Digitalmars-d-learn

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?


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Emmanuel Danso Nyarko via Digitalmars-d-learn

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!


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Imperatorn via Digitalmars-d-learn

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?


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Emmanuel Danso Nyarko via Digitalmars-d-learn

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.


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

also fails to compile while this works:

```d
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.




Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Dadoum via Digitalmars-d-learn

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:

```d
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

```c++
template 
struct List final
{
_d_dynamicArray< T > self;
List()
{
}
};

extern void hello(List arg);
```

)


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Basile B. via Digitalmars-d-learn

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.


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

also fails to compile while this works:

```d
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.


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Paul Backus via Digitalmars-d-learn

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`:

```d
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);
}
```


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Dadoum via Digitalmars-d-learn
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.


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

also fails to compile while this works:

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




Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Emmanuel Danso Nyarko via Digitalmars-d-learn

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'




Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Emmanuel Danso Nyarko via Digitalmars-d-learn

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:


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

Compiles fine with dmd, ldc2 and gdc.


```d
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.





Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Dadoum via Digitalmars-d-learn
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.


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Johan via Digitalmars-d-learn
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:


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

Compiles fine with dmd, ldc2 and gdc.


```d
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



Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Dadoum via Digitalmars-d-learn

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.


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Dadoum via Digitalmars-d-learn

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:


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

Compiles fine with dmd, ldc2 and gdc.


```d
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:

```c++
// Automatically generated by LDC Compiler

#pragma once

#include 
#include 
#include 
#include 

#ifdef CUSTOM_D_ARRAY_TYPE
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
#else
/// Represents a D [] array
template
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++:


```d
class Foo(T) {}

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

}
```

```c++
// Automatically generated by LDC Compiler

#pragma once

#include 
#include 
#include 
#include 

#ifdef CUSTOM_D_ARRAY_TYPE
#define _d_dynamicArray CUSTOM_D_ARRAY_TYPE
#else
/// Represents a D [] array
template
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 
class Foo;

extern void hello2(Foo* arg2);
```


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Imperatorn via Digitalmars-d-learn

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?


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

Compiles fine with dmd, ldc2 and gdc.


```d
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.


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Emmanuel Danso Nyarko via Digitalmars-d-learn

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?


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

Compiles fine with dmd, ldc2 and gdc.


```d
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.




Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Dadoum via Digitalmars-d-learn

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?


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

Compiles fine with dmd, ldc2 and gdc.


```d
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`


Re: Why can't we use strings in C++ methods?

2023-11-04 Thread Imperatorn via Digitalmars-d-learn

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?


Why can't we use strings in C++ methods?

2023-11-03 Thread Dadoum via Digitalmars-d-learn
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++.