www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Bug on C/C++ library to D, parameters suddenly becomming null or

reply Hipreme <msnmancini hotmail.com> writes:
I found some really strange problem happening when trying to 
create a binding between
cimgui (https://github.com/cimgui/cimgui), which is a 
automatically generated binding from the main C++ project 
(https://github.com/ocornut/imgui)

While trying to create a binding, everything worked until I 
wanted multiviewports.

The problem was caused by functions pointers members from a 
struct.

Inside the cpp code, I saw that the calling didn't change the 
viewport instance, but when arriving at the D code, the instance 
would be transformed in invalid.


The reference code I'm saying is:

Take a look onto

https://github.com/ocornut/imgui/blob/682249396f02b8c21e5ff333ab4a1969c89387ad/imgui.cpp#L11120

This line executes just correctly the viewport I just created on 
newviewport call from my D code.


While that line:

https://github.com/ocornut/imgui/blob/682249396f02b8c21e5ff333ab4a1969c89387ad/imgui.cpp#L11134

References some of the same viewports, but it strangely became 
invalid memory, while the line from getminimized are all working.

Things got even stranger when I compiled a DLL for not having to 
use my SDL implementation, only the OpenGL which I can't change 
because the OpenGL loader is the bindbc one.

This is a image from my debugger, where the program had break:

https://user-images.githubusercontent.com/10136262/96338382-79a9f700-1042-11eb-8f0f-f0d8155cd82e.png


As you can see, viewport is 0x000000 while void* param has some 
value.
While the c++ code did pass a viewport to the first parameter, as 
seem in:

https://github.com/ocornut/imgui/blob/682249396f02b8c21e5ff333ab4a1969c89387ad/imgui.cpp#L11634

This bug was mentioned in the cimgui repo, take a look as the 
reference:
https://github.com/cimgui/cimgui/issues/156

I solved this bug by casting void* param to ImGuiViewport, so, 
the first parameter was actually null while the second would be 
actually the first parameter.

The func prototype is correctly declared, although is a struct 
with a member callback which is assigned inside some D function.
It is a lot to read, but this bug is really strange for me and I 
don't know what to do else
Oct 17 2020
parent reply Avrina <avrina12309412342 gmail.com> writes:
On Saturday, 17 October 2020 at 18:03:45 UTC, Hipreme wrote:
 I found some really strange problem happening when trying to 
 create a binding between
 cimgui (https://github.com/cimgui/cimgui), which is a 
 automatically generated binding from the main C++ project 
 (https://github.com/ocornut/imgui)

 While trying to create a binding, everything worked until I 
 wanted multiviewports.

 The problem was caused by functions pointers members from a 
 struct.

 Inside the cpp code, I saw that the calling didn't change the 
 viewport instance, but when arriving at the D code, the 
 instance would be transformed in invalid.


 The reference code I'm saying is:

 Take a look onto

 https://github.com/ocornut/imgui/blob/682249396f02b8c21e5ff333ab4a1969c89387ad/imgui.cpp#L11120

 This line executes just correctly the viewport I just created 
 on newviewport call from my D code.


 While that line:

 https://github.com/ocornut/imgui/blob/682249396f02b8c21e5ff333ab4a1969c89387ad/imgui.cpp#L11134

 References some of the same viewports, but it strangely became 
 invalid memory, while the line from getminimized are all 
 working.

 Things got even stranger when I compiled a DLL for not having 
 to use my SDL implementation, only the OpenGL which I can't 
 change because the OpenGL loader is the bindbc one.

 This is a image from my debugger, where the program had break:

 https://user-images.githubusercontent.com/10136262/96338382-79a9f700-1042-11eb-8f0f-f0d8155cd82e.png


 As you can see, viewport is 0x000000 while void* param has some 
 value.
 While the c++ code did pass a viewport to the first parameter, 
 as seem in:

 https://github.com/ocornut/imgui/blob/682249396f02b8c21e5ff333ab4a1969c89387ad/imgui.cpp#L11634

 This bug was mentioned in the cimgui repo, take a look as the 
 reference:
 https://github.com/cimgui/cimgui/issues/156

 I solved this bug by casting void* param to ImGuiViewport, so, 
 the first parameter was actually null while the second would be 
 actually the first parameter.

 The func prototype is correctly declared, although is a struct 
 with a member callback which is assigned inside some D function.
 It is a lot to read, but this bug is really strange for me and 
 I don't know what to do else
You have to look at more than the declaration. The ABI depends on the types being passed as well. Unfortunately C++/C aren't direct translations with D and you hav to sometimes do hacks so that a D type is passed the same way as a C++ type. I'd investigate whether the type is POD or not. By the looks of it, it is being passed as a register.
Oct 17 2020
parent reply Hipreme <msnmancini hotmail.com> writes:
On Saturday, 17 October 2020 at 20:43:03 UTC, Avrina wrote:
 On Saturday, 17 October 2020 at 18:03:45 UTC, Hipreme wrote:
 [...]
You have to look at more than the declaration. The ABI depends on the types being passed as well. Unfortunately C++/C aren't direct translations with D and you hav to sometimes do hacks so that a D type is passed the same way as a C++ type. I'd investigate whether the type is POD or not. By the looks of it, it is being passed as a register.
So, I have finally solved the issue: I asked for help to the binding mantainer and it seems that when the C++ file gets compiled on MSVC it turns into a non-POD struct, while on MinGW and GCC it turns into a POD, so it was quite strange, it was solved by creating a function on the C side which would receive a pointer to this POD-mutating struct instead of returning and assigning its value on this _out parameter. The void* being the real parameter was related for some missing extern(System)
Oct 19 2020
parent Mike Parker <aldacron gmail.com> writes:
On Monday, 19 October 2020 at 17:49:24 UTC, Hipreme wrote:
 when the C++ file gets compiled on MSVC it turns into a non-POD 
 struct, while on MinGW and GCC it turns into a POD, so it was 
 quite strange,
As a general rule, you shouldn't mix binaries from MinGW and MSVC. Inconsistencies like this are bound to arise. DMD is implemeted to match MSVC. It's fine when loading C dlls dynamically, but as soon as you bring a linker or the C++ API into the picture, you'll hit issues eventually.
Oct 19 2020