C#调用C ++ DLL返回不正确的值

时间:2016-09-01 07:26:34

标签: c# c++ debugging dll

我没有进一步的想法如何调试这个bug,所以请求建议。

基本上,我有一个C ++ DLL,它有一个布尔函数

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被启动为false。代码中设置为true的唯一位置是记录器打印。 func的返回值也会定期打印到记录器。

C#导入函数如下:

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);

在某些情况下,从C#调用func会返回true,即使记录器将其显示为false - 常规打印为false,并且不会显示设置它的行。使用修改后的函数bool funcArg(SomeStruct & arg, bool & ret) { ret = some_var; }ret在相同条件下可靠地为假。

也许是最烦人/最令人困惑的部分:在func内添加调试打印时,它会返回正确的值。添加Sleep(500)时会发生同样的情况。这让我怀疑某种多线程恶作剧,但正如我所说 - 代码中只有一个地方some_var被指定为真,并且在此次运行中没有达到。

C#和C ++的交互是否可以解释这个问题?

1 个答案:

答案 0 :(得分:2)

您的问题的解决方案可以在您的声明之前进行以下编组。

[return:MarshalAs(UnmanagedType.I1)]

这可能发生,因为C将bool定义为4字节int,C ++将其定义为1字节。 C#团队决定在PInvoke期间使用4字节bool作为默认值,因为大多数系统API函数使用4字节值作为bool。如果要更改此行为,则必须使用编组指定要使用1个字节值。另一种解决方案可以是尝试将返回类型从bool更改为int,这也应该解决问题。

有关详细信息,请查看此处提到的答案: C# DllImport with C++ boolean function not returning correctly