How to pass a class by (const) reference to C++
evilrat
evilrat666 at gmail.com
Mon Dec 13 12:08:30 UTC 2021
On Monday, 13 December 2021 at 11:13:12 UTC, Tejas wrote:
> On Monday, 13 December 2021 at 09:21:26 UTC, Jan wrote:
>> 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.
>
> You'll have to use something called a
> [shim](https://en.wikipedia.org/wiki/Shim_(computing)), it
> seems.
>
> For example:
>
> `main.d` :
>
> ```d
>
> extern(C++) class A{}
>
> extern(C++) void cppFunc_shim(A arg);
>
> void main(){
> A a = new A();
> cppFunc_shim(a);
> }
>
> ```
>
> `cppShim.cpp` :
>
> ```c++
>
> class A{};
>
> extern void cppFunc(A const &arg);
>
> void cppFunc_shim(A *param){
> const A forwardingVar = A(*param);
> cppFunc(forwardingVar);
> }
>
> ```
>
> `cppFunc.cpp` :
>
> ```c++
>
> #include "iostream"
> class A{};
>
> void cppFunc(A const &arg){
> //std::cout << arg << std::endl;
> std::cout << "Called cppFunc :D" << std::endl;
> }
>
> ```
>
> Then pass the following on the command line(assuming all files
> are in the same directory):
>
> `ldmd2 main.d cppFunc.o cppShim.o -L-lstdc++`
>
> That's what it took to make it work for me, dunno if more
> convenient methods exist.
>
> Hope it helps :D
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.
More information about the Digitalmars-d-learn
mailing list