我没有进一步的想法如何调试这个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 ++的交互是否可以解释这个问题?
答案 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