Re: Small structs: interfacing with C++ potentially broken

2021-12-20 Thread Jan via Digitalmars-d-learn

On Monday, 20 December 2021 at 11:58:03 UTC, Tim wrote:

On Monday, 20 December 2021 at 10:24:00 UTC, Jan wrote:
Is this a known issue, or is there a way to instruct DMD to 
use a specific calling convention for a given type?


This looks like a bug. It seems to work without constructor in 
C++, but still crashes with a constructor in D. It also seems 
to work if a trivial destructor is added in D: ~this(){}


This could be related to POD types in C++. Structs with 
constructor or destructor are probably passed differently, but 
dmd only looks at the destructor.


Well, that at least gives me a way to work around this issue.


Small structs: interfacing with C++ potentially broken

2021-12-20 Thread Jan via Digitalmars-d-learn

I have a small struct that I'm trying to interface to.

C++
```cpp
struct __declspec(dllexport) SmallStruct
{
  float value = 0;
  //float value2 = 0;
  //float value3 = 0;

  SmallStruct(float val)
: value(val)
  {
  }

  static SmallStruct GetValue(float input)
  {
return SmallStruct(input * 3.141f);
  }
};
```

And on the D side:

```cpp
extern(C++) struct SmallStruct
{
  float value = 0;
//   float value2 = 0;
//   float value3 = 0;

  static SmallStruct GetValue(float input);
};
```

Then I use it like this:

```cpp
SmallStruct s = SmallStruct.GetValue(3);
```

Running this crashes on the C++ side, with an access violation 
writing data.
Looking at the disassembly, it seems that C++ expects the 
Smallstruct return object to be passed in, whereas D assumes that 
the SmallStruct is passed through registers.


This is with MVSC 2019 compiled for x64 and DMD v2.098.0.

If I enable 'value2' and 'value3', it seems that both compilers 
start to agree on the calling convention.


Is this a known issue, or is there a way to instruct DMD to use a 
specific calling convention for a given type?




Re: How to pass a class by (const) reference to C++

2021-12-16 Thread Jan via Digitalmars-d-learn

On Thursday, 16 December 2021 at 16:21:30 UTC, Tim wrote:
That looks like another bug in the compiler. pragma(mangle, 
...) should work as a workaround.


Another bug ticket it is then:
https://issues.dlang.org/show_bug.cgi?id=22604


Re: How to pass a class by (const) reference to C++

2021-12-16 Thread Jan via Digitalmars-d-learn

On Wednesday, 15 December 2021 at 22:50:38 UTC, Tim wrote:

On Wednesday, 15 December 2021 at 22:46:01 UTC, Jan wrote:
Btw. should I report this issue somewhere? Is far as I see 
this isn't logged yet:




Yes, it should be reported.


Ok, next problem. Maybe you know the necessary syntax for this 
one too.



C++
```cpp
class Test
{
public:
  __declspec(dllexport) static const int const_vars[2];
  __declspec(dllexport) static int nonconst_vars[2];
};

const int Test::const_vars[2] = {11, 23};
int Test::nonconst_vars[2] = {12, 24};
```

D
```cpp
extern(C++, class) struct Test
{
extern export static __gshared const(int)[2] const_vars;
extern export static __gshared int[2] nonconst_vars;
}
```

I get the nonconst_vars to link correctly, but for the const_vars 
the mangled name contains one less const than what MSVC 
generates, so I assume I have to wrap this somehow differently. I 
tried "const(int[2])" but that didn't make a difference.


D wants to link against:
`?const_vars@Test@@2PAHB`

which is:
`public: static int * const Test::const_vars" ()`

MSVC exports:
`?const_vars@Test@@2QBHB`

which is:
`public: static int const * const Test::const_vars`


Any idea?


Re: How to pass a class by (const) reference to C++

2021-12-15 Thread Jan via Digitalmars-d-learn

On Wednesday, 15 December 2021 at 22:50:38 UTC, Tim wrote:

On Wednesday, 15 December 2021 at 22:46:01 UTC, Jan wrote:
Btw. should I report this issue somewhere? Is far as I see 
this isn't logged yet:




Yes, it should be reported.


https://issues.dlang.org/show_bug.cgi?id=22603


Re: How to pass a class by (const) reference to C++

2021-12-15 Thread Jan via Digitalmars-d-learn

On Wednesday, 15 December 2021 at 22:33:15 UTC, Tim wrote:
I agree that __gshared should imply static. That's probably a 
bug in the compiler.


Using `extern` without `export` would only work with static 
linking (on Windows). `export` without `extern` would be 
exporting the variable for others, like `__declspec(dllexport)` 
in C++. `export` and `extern` combined imports the variable, 
like `__declspec(dllimport)`.


That's all very helpful, thanks for the explanations guys.

Btw. should I report this issue somewhere? Is far as I see this 
isn't logged yet:




Re: How to pass a class by (const) reference to C++

2021-12-15 Thread Jan via Digitalmars-d-learn

On Wednesday, 15 December 2021 at 21:30:47 UTC, Tim wrote:

It seems to work if var is additionally static:


Ha, it works indeed!

```cpp
extern export __gshared static int var;
```

That's a declaration worthy of C++ ! Fewer keywords would be too 
usable :D


Joking aside, I understood the docs such that `__gshared` 
actually *is* `static` in D, no? Also why the `export` when it's 
an extern variable?





Re: How to pass a class by (const) reference to C++

2021-12-15 Thread Jan via Digitalmars-d-learn

On Wednesday, 15 December 2021 at 17:10:51 UTC, Tim wrote:

Do you have a test case for your problem?


C++
```cpp
class Test
{
public:
  __declspec(dllexport) static int var;
};

int Test::var = 42;
```

D
```cpp
extern(C++, class) struct Test
{
  extern (C++) export extern __gshared int var;
}
```

(also tried without the duplicate extern(C++) and without 
'export')


DLL compiled with Visual Studio 2019. D DLL compiled with a 3 day 
old nightly build of DMD.


DMD says:
`error LNK2019: unresolved external symbol "public: static int 
Test::var" (?var@Test@@2HA)`


I've checked the .exp file of the DLL where the symbol is defined 
in, and it has the exact same name there. And yes, I correctly 
link against that DLL in general, other symbols located in that 
DLL are linked just fine by DMD.





Re: How to pass a class by (const) reference to C++

2021-12-15 Thread Jan via Digitalmars-d-learn

On Wednesday, 15 December 2021 at 12:36:49 UTC, evilrat wrote:
You probably know this but just in case - unlike C++ in D 
variables by default have thread local storage, to link with 
C++ global variable you need to use __gshared storage modifier 
in D, it is similar to 'shared' variable that unlike 'shared' 
tells the compiler "I know how to synchronize it myself".


```d
module a;

struct Foo {}

extern(C++)
__gshared Foo globalFoo;
```


Yeah, did that. As I said the mangled name that DMD chose is 
correct.


As I was told linking against functions in DLLs works perfectly, 
because it is identical to static linking. Linking against 
global/static variables supposedly differs and that's not handled 
correctly for DLLs. As I said, I talked to someone who worked on 
fixing lots of those issues a while ago and he immediately knew 
about this limitation.


Re: How to pass a class by (const) reference to C++

2021-12-15 Thread Jan via Digitalmars-d-learn
On Wednesday, 15 December 2021 at 11:03:27 UTC, rikki cattermole 
wrote:


On 15/12/2021 11:54 PM, Jan wrote:

On Wednesday, 15 December 2021 at 09:36:54 UTC, Jan wrote:
Unfortunately it's the "annoying little details" that I 
immediately bumped into.


Just another example: I just learned that linking against C++ 
DLLs is quite limited. I ran into the issue that linking in an 
external variable doesn't work (even though the mangled name 
that D chooses is correct), because DLLs work differently than 
static linking does.
Someone with more in-depth knowledge told me, that Windows 
support in D and specifically DLL support is lacking quite a 
bit.


Having *only* link compatibility is totally fine, D currently 
just doesn't fulfill that promise, especially not on Windows 
and especially not with DLLs.


Are you sure that on the shared library side it was marked as 
exported?


If a symbol is not exported, there is no guarantee (nor reason 
to think) that it will be visible during runtime linking to 
said shared library/executable.


This isn't unique to D, its just how linkers work.


Yep, checked that. Even checked the .exp file and compared the 
mangled name there with the mangled name that D tries to use, 
they are the same. I know someone who worked on improving DLL 
support for D a while back and he said he had to fix this in D 
but didn't get that merged into DMD back then (since there were 
many other things as well) and now he doesn't have time to work 
on it further :(


Re: How to pass a class by (const) reference to C++

2021-12-15 Thread Jan via Digitalmars-d-learn

On Wednesday, 15 December 2021 at 09:36:54 UTC, Jan wrote:
Unfortunately it's the "annoying little details" that I 
immediately bumped into.


Just another example: I just learned that linking against C++ 
DLLs is quite limited. I ran into the issue that linking in an 
external variable doesn't work (even though the mangled name that 
D chooses is correct), because DLLs work differently than static 
linking does.
Someone with more in-depth knowledge told me, that Windows 
support in D and specifically DLL support is lacking quite a bit.


Having *only* link compatibility is totally fine, D currently 
just doesn't fulfill that promise, especially not on Windows and 
especially not with DLLs.


Re: How to pass a class by (const) reference to C++

2021-12-15 Thread Jan via Digitalmars-d-learn

On Tuesday, 14 December 2021 at 07:50:48 UTC, evilrat wrote:
There is some missing features like above tail ref and const, 
there is minor mangling issues that requires pragma mangle 
sometimes, and other annoying little details.


As far as I can tell from my limited experience, the way D 
approaches interacting with C++ is sound and extremely useful. 
Link compatibility goes a very long way.


Unfortunately it's the "annoying little details" that I 
immediately bumped into. Things that should be no problem at all 
with just link compatibility, like incorrectly mangled functions 
(forgetting about 'const' in return types on Windows) and this 
very, very annoying issue that I can't pass a class by reference 
but only by pointer.


I can understand that passing a class by value might be out of 
scope (though it would be possible, since it works for structs 
just as well), but with pass by reference it's really just D's 
boneheadedness to try to have its own way.


D is a great language, and I want to use it, but as a stand-alone 
language it just doesn't have the ecosystem that I need 
(gamedev). Using it as an integrated scripting language is for me 
the next best thing to benefit from it in a project that is 
otherwise C++. With link compatibility and auto-generating some 
bindings, I can get there eventually, but it's still a lot of 
work with many manually crafted shims. I am currently willing to 
invest a lot of time to try to solve this, but I won't rewrite a 
huge C++ code base just because D can't pass classes by reference.


Other projects will have even more constraints and even less 
willingness to invest time into such an undertaking and just 
scrap the idea early on.


C++ link compatibility was a great idea, but if D wants to expand 
it's user base further, in my opinion it has to polish the 
interop and be willing to make a few sacrifices on it's end, 
because that can save everyone else hundreds of hours of tedious 
work (and maintenance) and thus be the deciding factor for or 
against using D in a C++ project.




Re: How to pass a class by (const) reference to C++

2021-12-13 Thread Jan via Digitalmars-d-learn
On Monday, 13 December 2021 at 12:16:03 UTC, Ola Fosheim Grøstad 
wrote:

On Monday, 13 December 2021 at 12:08:30 UTC, evilrat wrote:
Yeah but it sucks to have making C++ wrapper just for this. I 
think either pragma mangle to hammer it in place or helper 
dummy struct with class layout that mimics this shim logic is 
a better solution in such cases.

Literally anything but building C++ code twice for a project.


Does something like this work?


```
class _A {}
struct A {}

extern(C++) void CppFunc(ref const(A) arg);

void func(_A a){
CppFunc(*cast(A*)a);
}
```


Unfortunately no. Maybe the cast would even make it work, but I 
can't have "A" and "_A" in D as separate types, because the class 
is supposed to link to C++ functions and thus renaming it from A 
to _A breaks that. On the other hand I can't give the struct 
another name either, because that's how it is linked to in 
"CppFunc".




Re: How to pass a class by (const) reference to C++

2021-12-13 Thread Jan via Digitalmars-d-learn

On Monday, 13 December 2021 at 16:29:12 UTC, Tim wrote:
I made a pull request, which changes the mangling to tail const 
for classes passed directly as parameter or return type, but 
now think this would break too much code: 
https://github.com/dlang/dmd/pull/13369
The proposal to add a deref-type-constructor, would also allow 
to have tail const classes.


A 'deref' keyword sounds interesting. I'm not an expert on 
compilers, but thinking about this a bit more, to me it looks 
like the fundamental problem is, that D tries to apply its class 
pointer/reference semantics to C++, even though it could do this 
differently. 'Deref' would only solve one (common) issue. 
However, in C++ it is also very common to treat classes as value 
types. Maybe one could give such a hint to the D compiler instead.


If I have this C++ code:
```cpp
class A { ... };

void AsValue(A value);
void AsPtr(A* value);
void AsConstPtr(const A* value);
void AsRef(A& value);
void AsConstRef(const A& value);
```

Afaik today I can really only bind to functions of the form 
'AsPtr' and 'AsConstPtr'. And if I declare A in D as a struct, I 
could also bind to all the others, but as mentioned above that's 
not always possible.


How about in D I could declare that A should be used like a value 
type to pass it to a function, using the 'struct' keyword:


```cpp
extern(C++) class A { ... }
extern(C++) void AsValue(struct A value);
extern(C++) void AsPtr(A value); // could stay as previously, OR
extern(C++) void AsPtr(struct A* value); // same as above
extern(C++) void AsConstPtr(const(A) value);
extern(C++) void AsConstPtr(const(struct A*) value); // same as 
above

extern(C++) void AsRef(ref struct A value);
extern(C++) void AsConstRef(const(ref struct A) value); // same 
as above

```

So here the 'struct' keyword would tell the compiler to treat A 
like a value type, just as in C++ and thus apply pointer, const 
and reference semantics like in C++. Additionally, if a pure 
'struct A' is encountered, the compiler would need to create a 
copy of the object on the stack, just as it would do for structs, 
to pass it to C++ (which might modify the temporary). I guess 
this would be trickier to implement but then you would be able to 
pass classes to C++ under all circumstances.


The added benefit would be, that this shouldn't change existing 
behavior and thus not break anything.


Unfortunately I have neither the time nor expertise to change DMD 
myself.


Re: How to pass a class by (const) reference to C++

2021-12-13 Thread Jan via Digitalmars-d-learn
On Monday, 13 December 2021 at 13:02:50 UTC, Ola Fosheim Grøstad 
wrote:

On Monday, 13 December 2021 at 12:51:17 UTC, evilrat wrote:
That example is still looks very conspicuous because it is 
very likely does nothing on the caller side in C++ as it 
passes a copy.


Yes, I wouldn't want to use it, maybe manual mangling is 
better, but still painful. ```const A&``` is so common in C++ 
API's that it really should be supported out-of-the-box.  All 
it takes is adding a deref-type-constructor to the D language 
spec, e.g. ```ref const(@deref(A))```


I fully agree. This pattern is so common in C++, that I am 
surprised D doesn't have a way to do this already. The whole idea 
of linking against C++ is to interop easily, with little friction 
and high performance. Needing to build any shims or redesign the 
C++ side is very much contrary to this goal.


Does anyone know whether such issues have been discussed before? 
I can't imagine I'm the first one to run into this.


Re: How to pass a class by (const) reference to C++

2021-12-13 Thread Jan via Digitalmars-d-learn

On Monday, 13 December 2021 at 07:48:34 UTC, evilrat wrote:

On Sunday, 12 December 2021 at 21:24:39 UTC, Jan wrote:

In D I have an extern(C++) class:

```cpp
extern(C++) class A
{
~this();

// other stuff
}
```

An a function that takes A by const reference:

```cpp
void CppFunc(const A& arg);
```

But how do I bind this in D ?

```cpp
extern(C++) void CppFunc(A arg); // tries to pass as 'A*'
extern(C++) void CppFunc(ref const(A) arg); // tries to pass 
as 'A const * const &'

```

I have solved similar problems with other classes by declaring 
them as struct in D, but that only works for classes that have 
no virtual functions. I now have a class where I do need to 
use a class on the D side, and now I have problems passing 
these objects to C++.


You can tell compiler to mangle it as struct/class using 
extern(C++, struct).


```d
extern (C++, struct) // will use struct mangling even though 
it's a class

class SomeDClass
{
 ...
}
```


I tried this, but it doesn't work, because it seems D decides how 
to pass the object by whether it is a class or struct in D, not 
in C++. So even with the change as you suggested it, it still 
tries to pass the object as a pointer to begin with.


How to pass a class by (const) reference to C++

2021-12-12 Thread Jan via Digitalmars-d-learn

In D I have an extern(C++) class:

```cpp
extern(C++) class A
{
~this();

// other stuff
}
```

An a function that takes A by const reference:

```cpp
void CppFunc(const A& arg);
```

But how do I bind this in D ?

```cpp
extern(C++) void CppFunc(A arg); // tries to pass as 'A*'
extern(C++) void CppFunc(ref const(A) arg); // tries to pass as 
'A const * const &'

```

I have solved similar problems with other classes by declaring 
them as struct in D, but that only works for classes that have no 
virtual functions. I now have a class where I do need to use a 
class on the D side, and now I have problems passing these 
objects to C++.


Re: C++ bindings: const(T) dropped in return types of templates ?

2021-12-09 Thread Jan via Digitalmars-d-learn

On Thursday, 9 December 2021 at 07:58:46 UTC, frame wrote:

On Thursday, 9 December 2021 at 07:41:32 UTC, frame wrote:

On Monday, 6 December 2021 at 20:31:47 UTC, Jan wrote:

So am I missing something, or did the compiler somehow forget 
about the const-ness?


Sounds like a bug to me, eg this one:
https://issues.dlang.org/show_bug.cgi?id=20685


But this is no show stopper, you can always force the mangling 
with the pragma directive.

https://dlang.org/spec/pragma.html#mangle


Oh it's a known bug for over a year already :(

It is a bit of a show stopper for me, since the mangled name that 
I have isn't always correct (CastXML uses Clang and that seems to 
pick different calling conventions sometimes, than what MSVC 
would do, so the mangled names that I get are not guaranteed to 
be correct).


Well, I'll work around it for now, thanks for the answer.


C++ bindings: const(T) dropped in return types of templates ?

2021-12-06 Thread Jan via Digitalmars-d-learn
I am trying to auto-generate bindings for C++ code in D. I've 
come across something that looks like a bug in DMD to me, but 
since I'm such a newbie in D maybe I am missing something.


My C++ class looks like this:

```cpp
template 
struct Vec3Template
{
  static const Vec3Template ZeroVector();
};
```

And my D binding code looks like this:

```cpp
extern(C++) struct Vec3Template(TYPE)
{
  static const(Vec3Template!(TYPE)) ZeroVector();
}
alias Vec3 = Vec3Template!(float);
```

However, when I try to use Vec3.ZeroVector() I am getting a 
linker error about unresolved symbols. It works with other 
functions, the error is specific to this function.


Now it complains that it can't find this one:
`?ZeroVector@?$Vec3Template@M@@SA?AU1@XZ`

However, I am using castXml to extract my C++ information, and 
that says that the mangled name should be:

`?ZeroVector@?$Vec3Template@M@@SA?BU1@XZ`

Running both names through undname.exe, an MSVC tool that 
generates the undecorated function name from the mangled name, it 
says that the latter function definition should be:
`public: static struct Vec3Template const __cdecl 
Vec3Template::ZeroVector(void)`


Whereas the former definition would be:
`public: static struct Vec3Template __cdecl 
Vec3Template::ZeroVector(void)`


So the one that D tries to link against is missing the `const`.

However, unless I misunderstood how to apply const to a type in 
D, you can see that I did wrap the type in const(). (I also tried 
immutable, but that's not allowed for extern C++ code).


So am I missing something, or did the compiler somehow forget 
about the const-ness?


I'm currently using DMD64 D Compiler v2.098.0-dirty


Re: C++/D class interop example crashes

2021-03-27 Thread Jan via Digitalmars-d-learn

On Saturday, 27 March 2021 at 18:39:53 UTC, Bastiaan Veelo wrote:
The example links objects statically. You may be experiencing 
additional challenges with crossing DLL boundaries. I have not 
yet used DLLs, but did you initialise the D runtime?


I haven't done anything extra (I'm pretty new to D). Do you mean 
calling this from the D code before using writeln?

https://dlang.org/phobos/core_runtime.html#initialize

I would have thought that happens automatically anyway.


C++/D class interop example crashes

2021-03-27 Thread Jan via Digitalmars-d-learn

I just tried to get this example to work:
https://dlang.org/spec/cpp_interface.html#using_d_classes_from_cpp

It kept crashing for me with a 'privileged instruction' error 
when the function 'bar' was executed. Finally I removed the call 
to writefln and voilà it finally works.


So why does it fail? I assumed the standard library functions 
should all work.
I'm compiling with "dmd -shared -m64 -debug" and link against a 
C++ DLL that was built with VS2019. Should the D DLL not contain 
everything to be self-sufficient to use it's entire runtime 
functionality?

And if not, what other functions might be problematic?

Also, if anyone here has contacts to the people that maintain the 
samples, maybe someone should adjust the sample to not contain 
code that may break this way.


Re: Mimicking a shell

2020-01-06 Thread Jan via Digitalmars-d-learn
I think the suggestion of angel would be most fitting for my 
case. As angel said, the using the C code for D would be a 
relatively small refactor.


if you want to send like a synthetic arrow keystroke, well, 
things get ugly again, it will need to send the right series of 
bytes based on what terminal the program thinks you are.


Using arrow key etc. would be very beneficial for my case. So I 
thank Adam for his solution, but I prefer angel's one.


Thanks guys :)



Re: Mimicking a shell

2020-01-04 Thread Jan via Digitalmars-d-learn

On Sunday, 29 December 2019 at 19:21:53 UTC, Adam D. Ruppe wrote:

On Sunday, 29 December 2019 at 17:03:14 UTC, Jan wrote:

Is there a way to forward all input and output from a shell?


yes, but it is platform specific and can be a decent amount of 
code.


what OS are you on?


I am using Linux (Fedora).

Thanks, @angel. I'll take a look at your suggestion :)


Mimicking a shell

2019-12-29 Thread Jan via Digitalmars-d-learn

Hi,

Is there a way to forward all input and output from a shell? This 
implies that e.g. pressing the left arrow on the keyboard is 
immediately being forwarded to the shell and that the output from 
a shell would be *exactly* the same as output from my D program 
(that would include the prompt and VGA colouring).


Kind regards,
Jan


Re: Pass 'this' as reference

2018-09-19 Thread Jan via Digitalmars-d-learn
On Saturday, 15 September 2018 at 20:13:51 UTC, Jonathan M Davis 
wrote:
On Saturday, September 15, 2018 11:44:05 AM MDT Jan via 
Digitalmars-d-learn wrote:

[...]


No. variables are _always_ lvalues. An lvalue is an object 
which is addressable and which can therefore be assigned a 
value (ignoring issues of constness). The name comes from the 
fact that lvalues are allowed on the left-hand side of an 
assignment operation, whereas rvalues are only allowed on the 
right. e.g.


[...]


Many thanks Jonathan! :)


Re: Pass 'this' as reference

2018-09-15 Thread Jan via Digitalmars-d-learn
On Thursday, 13 September 2018 at 11:08:30 UTC, Jonathan M Davis 
wrote:

[...]


Thanks for clarifying Jonathan :)
But aren't the variables considered rvalues then?


Re: Pass 'this' as reference

2018-09-13 Thread Jan via Digitalmars-d-learn

Many thanks Adam and Steve! Works like a charm! :D
I presumed classes are lvalues. I shouldn't make things more 
complicated than they are ;-)


Pass 'this' as reference

2018-09-12 Thread Jan via Digitalmars-d-learn
I'm using D not for that long and lately I have encountered an 
issue. I have class 'Foo' with a constructor using this signature:

`this (ref Bar original)`

In the 'Bar' class itself I want to create an instance of 'Foo' 
using 'this' as parameter. Something in the way of:

`Foo foo = new Foo(ref this);`

I couldn't find anything interesting on the internet to help me. 
Could anyone help me? Many thanks in advance!