C#P / Invoke 2维数组

时间:2016-02-08 08:32:17

标签: c# arrays pinvoke

我试图用C#代码调用C函数:

typedef char IPTriggerNameType[256];
typedef unsigned long COMM_HANDLE;
typedef BYTE GUID_TYPE[16];
typedef long LONGINT;

typedef struct  {
    GUID_TYPE           Guid;   
    IPTriggerNameType   Name; 
}IPCAM_GENERIC_EVENT_ID;

typedef struct  {
    IPCAM_GENERIC_EVENT_ID      EventId;   
    LONGINT                     RelatedTriggerId;
    LONGINT                     ObsoleteEvent;
}IPCAM_GENERIC_EVENT_INFO;

typedef struct
{
    LONGINT                     NumOfEvents;
    IPCAM_GENERIC_EVENT_INFO    *GenericEventsList;
}VID_CHANNEL_GENERIC_EVENTS_STRUCT;


int __stdcall GetGenericEvents( 
/*  Inputs: */
    COMM_HANDLE                         Handle,                         
    LONGINT                             MaxNumOfChannelsInTable,
    LONGINT                             MaxNumOfEventsPerChannel,

/*  Outputs: */    
    LONGINT                             *NumOfChannels,
    VID_CHANNEL_GENERIC_EVENTS_STRUCT   *ChannelsEventsTable);

和C#等价物如下:

[StructLayout(LayoutKind.Sequential)]
    public struct IPCAM_GENERIC_EVENT_ID
    {
        [MarshalAs(UnmanagedType.LPArray, SizeConst = 16)]
        public byte[] Guid;

        [MarshalAs(UnmanagedType.LPArray, SizeConst = 256)]
        public char[] Name;
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct IPCAM_GENERIC_EVENT_INFO
    {
        public IPCAM_GENERIC_EVENT_ID EventId;
        public int RelatedTriggerId;
        public int ObsoleteEvent;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct VID_CHANNEL_GENERIC_EVENTS_STRUCT
    {
        public int NumOfEvents;

        [MarshalAs(UnmanagedType.LPArray, SizeConst = 100)]
        public IPCAM_GENERIC_EVENT_INFO[] GenericEventsList;
    }

    [DllImport(dllName)]
public static extern int GetGenericEvents(
    /*  Inputs: */
    int Handle,
    int MaxNumOfChannelsInTable,
    int MaxNumOfEventsPerChannel,

    /*  Outputs: */
    out int NumOfChannels,
    out VID_CHANNEL_GENERIC_EVENTS_STRUCT[] ChannelsEventsTable);


int numOfChannels = 16, actualNumOfChannels = 0;
int maxNumOfEvents = 100;

VID_CHANNEL_GENERIC_EVENTS_STRUCT[] genericEventsList = new VID_CHANNEL_GENERIC_EVENTS_STRUCT[numOfChannels];
for (int i = 0; i < numOfChannels; i++)
{
    genericEventsList[i].GenericEventsList = new IPCAM_GENERIC_EVENT_INFO[maxNumOfEvents];
}

GetGenericEvents(conn, numOfChannels, maxNumOfEvents, out actualNumOfChannels, out genericEventsList);

当调用C#方法时,我得到异常,导致应用程序崩溃:

  

托管调试助手'FatalExecutionEngineError'检测到了   'My.exe'中的问题。

     

其他信息:运行时遇到致命错误。该   错误的地址是0x72a6cf41,在线程0x5a98上。错误   代码是0xc0000005。此错误可能是CLR或中的错误   用户代码的不安全或不可验证部分。这个的常见来源   错误包括COM-interop或PInvoke的用户封送错误   可能会破坏堆栈。

我做错了什么?

1 个答案:

答案 0 :(得分:-1)

字段:

VID_CHANNEL_GENERIC_EVENTS_STRUCT.GenericEventsList

是一个指针,声明为:

IPCAM_GENERIC_EVENT_INFO *GenericEventsList

但是你将它声明为一个数组,包含在结构中:

[MarshalAs(UnmanagedType.LPArray, SizeConst = 100)]
public IPCAM_GENERIC_EVENT_INFO[] GenericEventsList;

您可以尝试使用IntPtr和Marshal.AllocHGlobal。看看这个:How use pinvoke for C struct array pointer to C#