1

我有一个用 C++ 编码的闭源非托管 DLL,我想在 C# 解决方案中使用它,所以我创建了一个使用 P/Invoke 调用闭源 DLL 函数的包装器托管 DLL。这对于没有参数函数和 int 变量非常有效。但是,当运行一个更复杂的函数时,我得到一个 System.ExecutionEngineException,该函数将结构数组作为参数,其中包含字符串的字符数组。这是我所拥有的:

[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 使用的部分内存,则可能会抛出此异常。不幸的是,我无法验证这一点。我的代码中是否存在明显错误并可能导致问题的地方?

4

2 回答 2

2

嗯,我认为您的问题出在 refTarget[] targets参数上。AFAIR 这是对引用的引用,这可能不是您真正想要的。

我会试试这个:

[DllImport("tyrfde.dll", EntryPoint = "tyrfdeGetTargets")]
public static extern int GetTarget([Out, MarshalAs(UnmanagedType.LPArray)] Target[] targets);

也许这篇文章可以帮助您找到正确的声明。

注意这里数组的大小并不清楚,通常在这种情况下还有一个ref int length参数,然后可以MarshalAs通过SizeParameterIndex属性在属性中引用。

于 2009-12-02T14:56:38.687 回答
0

1) 你确定 TCharA 是 16 位的吗?否则我认为您还应该指定要使用的 whar CharSet。

2) 在 C++/CLI 中编写这种包装器要简单得多。

于 2009-12-02T15:03:37.283 回答