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