Reputation: 561
I have no further ideas how to debug this bug, so asking for advice.
Essentially, I have a C++ DLL, which has a boolean function
class Point
{
Public:
double x;
double y;
// lots of operators
}
typedef struct SomeStructParent
{
bool isValid;
int64_t StartTime;
int64_t EndTime;
} SomeStructParent;
typedef struct SomeStruct : SomeStructParent
{
Point Center;
} SomeStruct;
bool func(SomeStruct & arg)
{ return some_var; }
some_var
is initiated to false. The only place in the code where it is set to true has a logger printing. The return value of func is also printed to logger regularly.
C# imports the function like so:
public struct EtPoint
{
public double x;
public double y;
}
[StructLayout(LayoutKind.Sequential)]
public struct SomeStruct
{
bool isValid;
// in milliseconds using tracker epoch
public long StartTime;
long EndTime;
public EtPoint Center;
}
[DllImport("ETHAL.dll", EntryPoint = "func", CallingConvention = CallingConvention.Cdecl)]
public static extern bool func(ref SomeStruct data);
Under some conditions, calling func
from C# returns true, even though the logger shows it as false - the regular prints are false and the line that shows it was set does not occur. With a modified function bool funcArg(SomeStruct & arg, bool & ret) { ret = some_var; }
, ret
is reliably false under the same conditions.
Perhaps the most annoying/perplexing part: when adding a debug print inside func
, it returns the correct value. The same happens when I add Sleep(500)
. This makes me suspect some kind of multithreading shenanigans, but as I said - only one place in the code where the some_var
is assigned true, and it isn't reached in this run.
Is there something with the interaction of C# and C++ that could account for this?
Upvotes: 0
Views: 845
Reputation: 144
A solution to your problem can be to precede your declaration withe the following marshaling.
[return:MarshalAs(UnmanagedType.I1)]
This may happen because C defines bool as 4 bytes int and C++ defines it as 1 byte. C# team decided to use 4 byte bool as default during PInvoke because most of the system API function use 4 bytes values as bool. If you want to change this behavior you have to do it with marshaling specifying that you want to use 1 byte value. Also another solution can be to try changing the return type from bool to int, that should also fix the issue.
For more information, have a look at the answer mentioned here: C# DllImport with C++ boolean function not returning correctly
Upvotes: 2