获取System.ExecutionEngineException错误调用C语言中传递结构数组的C函数

时间:2012-01-10 14:39:09

标签: pinvoke marshalling

我正在构建一个围绕C dll用C#编写的COM包装器,当我调用一个引用预先初始化的结构数组的特定函数时出现错误。

错误是:“sXEposCOM.dll中出现'System.ExecutionEngineException类型'的未处理异常”

C函数的签名如下:

UINT16 sXGetSupportedSchemes( SXEposScheme_t *pSchemes );

C dll中的SXEposScheme_t结构声明为:

typedef struct _SXEposScheme_t
{
BYTE    schemeID[SX_EPOS_SID_LENGTH];
char    schemeName[SX_EPOS_MAX_SCHEME_NAME_LENGTH];
} SXEposScheme_t;

在我的C#包装器(sXEposCOM)中,我有以下内容:

private const int SX_EPOS_SID_LENGTH    = 2;
private const int SX_EPOS_MAX_NUM_SCHEMES = 10;

[DllImport("SXEposDll.dll")]
private static extern UInt16 sXGetSupportedSchemes(ref SXEposScheme_t [] pSchemes);

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SXEposScheme_t
{
    [MarshalAs(
    UnmanagedType.ByValArray,
    SizeConst = SX_EPOS_SID_LENGTH)]
    public byte[] schemeID;
    [MarshalAs(
    UnmanagedType.ByValArray,
    SizeConst = SX_EPOS_MAX_SCHEME_NAME_LENGTH)]
public char [] schemeName;
}

public int GetSupportedSchemes()
{
    uint result = 0;
    uint schemeCnt = 0;
    GetNumSchemes(ref schemeCnt); //This call to the C dll succeeds and returns 2 to   schemeCnt

    SquidEposScheme_t[] schemes = new SXEposScheme_t[schemeCnt];    
    result = sXGetSupportedSchemes(ref schemes); //Errors on this line with An unhandled exception of type 'System.ExecutionEngineException occurred in sXEposCOM.dll

...
...
return result;
}       

有谁能告诉我为什么会收到此错误?

1 个答案:

答案 0 :(得分:1)

当本机代码破坏垃圾收集堆时会触发此异常。这里有很多机会,你的C#声明看起来不对。数组已作为指针传递,将 ref 添加到参数使其成为指针的指针。可能的解决方法:

[DllImport("SXEposDll.dll")]
private static extern UInt16 sXGetSupportedSchemes([In,Out] SXEposScheme_t [] pSchemes);

Pack = 1非常不合适,使用ByValTStr编组一个字符串。可能的解决方法:

[StructLayout(LayoutKind.Sequential)]
public struct SXEposScheme_t
{
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = SX_EPOS_SID_LENGTH)]
    public byte[] schemeID;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = SX_EPOS_MAX_SCHEME_NAME_LENGTH)]
    public string schemeName;
}