-1

I am trying to call a C function from C# code:

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);

and the C# equivalent is as follows:

[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);

when calling the C# method I get exception which crashes the application:

Managed Debugging Assistant 'FatalExecutionEngineError' has detected a problem in 'My.exe'.

Additional information: The runtime has encountered a fatal error. The address of the error was at 0x72a6cf41, on thread 0x5a98. The error code is 0xc0000005. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

What am I doing wrong ?

2
  • SizeConst = 100 means C# will always try to read 100 items, which is most probably an out-of bounds access (possible access violation). Besides, a char is one byte in C++, but it's 2 bytes in C#. Commented Feb 8, 2016 at 8:50
  • There are many errors in your code. But it's not actually possible to tell you what the code should be because you don't say how the C++ code is to be called. Knowing the definition of the types is not enough. You need to know the semantics too. You'll need to consult the documentation and some example C++ code that calls these functions. If you have the source of the C++ code that will help. I'll leave my answer for a little while but it really should be deleted since the question can't readily be answered in full. Commented Feb 8, 2016 at 9:00

1 Answer 1

-1

The field:

VID_CHANNEL_GENERIC_EVENTS_STRUCT.GenericEventsList

is a pointer, declared as:

IPCAM_GENERIC_EVENT_INFO *GenericEventsList

But you are declaring it as an array, included in the struct:

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

You may try to use an IntPtr and Marshal.AllocHGlobal. Check this out: How use pinvoke for C struct array pointer to C#

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.