2009-12-02 78 views
1

我有一个封闭源代码的非托管DLL用C++编写,我想在C#解决方案中使用,所以我创建了一个使用P/Invoke调用封闭源代码DLL函数的包装管理DLL。对于没有param函数和int变量,这很好。但是,当运行一个更复杂的函数时,我得到一个System.ExecutionEngineException,该函数将一个结构数组作为参数包含字符串的char数组。这里是我有什么:P/Invoke throw 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); 

不明白为什么数组的大小被指定为长,但无论如何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

您还应该发布一个实际分配数组并调用该函数的示例。问题可能在那里。看起来奇怪的是,如果函数接受一个指向'N'元素的指针,它也不需要数组中元素的个数作为第二个参数。 – arul 2009-12-02 15:04:48

回答

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参数,然后可以通过SizeParameterIndex属性在MarshalAs属性中引用该参数。

+0

你的[MarshalAs(UnmanagedType.LPArray)]停止错误抛出,但我的数组没有被函数填充。这不就是裁判在那里的原因吗? – 2009-12-02 15:30:01

+0

啊,数组被填充的功能...在这种情况下,你需要添加一个[Out]属性。尝试编辑的代码。 – Lucero 2009-12-02 15:32:32

+0

编辑版本的作品。谢谢,任何想法为什么语法不是:GetTarget([MarshalAs(UnmanagedType.LPArray)] out Target [] targets); – 2009-12-02 15:40:16

0

1)你确定TCharA是16位吗?否则,我认为你也应该指定whar CharSet来使用。 2)编写这种类型的包装器在C++/CLI中更简单一些。

+0

对于1:我没有类型定义,所以我不是绝对确定的,但是是一个公平的猜测。 2:从previousle提到的文章:如果非托管API打包为DLL并且源代码不可用,P/Invoke是唯一的选项 – 2009-12-02 15:27:53

+0

1.行,2.我认为你弄错了。 C++/CLI程序集允许您在仍处于“托管地”时包含.h文件和/或链接到.lib文件。它仍然倾向于命名C++/CLI cde使“P/Invoke”取决于您的调用... :-) – 2009-12-02 16:07:19