简体   繁体   中英

C# calling C++ DLL returns incorrect value

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; } 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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM