我有一个用C ++编码的封闭源非托管DLL我想在C#解决方案中使用,所以我创建了一个使用P / Invoke来调用封闭源DLL函数的包装器托管DLL。对于没有param函数和int变量,这非常有效。但是,当运行一个更复杂的函数时,我得到一个System.ExecutionEngineException,该函数将一个struct数组作为参数,该参数包含字符串的char数组。这就是我所拥有的:
[StructLayout(LayoutKind.Sequential)]
public struct Target
{
public int targetID;
public string Label;
}
[DllImport("tyrfde.dll", EntryPoint = "tyrfdeGetTarget")]
public static extern int GetTarget(ref Target[] targets);
以下是我从DLL的头文件中获得的信息:
#define TARGET_LBL_SIZE (256l)
typedef struct _tyrfdeTarget
{
TInt32 TargetID; // integer signed 32bits
TCharA Label[TARGET_LBL_SIZE]; // caracter
} tyrfdeTarget;
TInt32 __stdcall tyrfdeGetTargets(tyrfdeTarget* pTargets);
不太确定为什么数组大小指定为long,但无论如何SizeConst只接受int。经过一些搜索,这是我试图解决的问题。
[StructLayout(LayoutKind.Sequential, Size = 260), Serializable]
public struct Target
{
public int targetID;
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 256)]
public string Label;
}
[DllImport("tyrfde.dll", EntryPoint = "tyrfdeGetTargets")]
public static extern int GetTarget(ref Target[] targets);
但我仍然有问题。我已经读过,如果函数清除了CLR使用的内存的一部分,则会抛出此异常。不幸的是我无法验证。我的代码中是否存在明显错误并可能导致问题的内容?
答案 0 :(得分:2)
嗯,我认为您的问题在于参考Target[] targets
参数。 AFAIR这是对参考的引用,这可能不是你真正想要的。
我试试这个:
[DllImport("tyrfde.dll", EntryPoint = "tyrfdeGetTargets")]
public static extern int GetTarget([Out, MarshalAs(UnmanagedType.LPArray)] Target[] targets);
也许this article可以帮助您找到正确的声明。
请注意,此处的数组大小不明确,通常在这种情况下还会有ref int length
参数,然后可以通过MarshalAs
在SizeParameterIndex
属性中引用该参数属性。
答案 1 :(得分:0)
1)你确定TCharA是16位吗?否则我认为你还应该指定使用whar CharSet。
2)在C ++ / CLI中编写这种包装器更简单。