C # callback function call from C DLL

I am writing a C # application in Windows CE 6 for monitoring a 3G modem. The application will call functions in the C DLL to access the modem.

When launched, the C # application will call this function to create a new connection:

[DllImport("swmodem.dll", CallingConvention = CallingConvention.Winapi)] public static extern int CreateDataConnection(EVENT_CALLBACK callback); 

EVENT_CALLBACK is defined as:

 public delegate void EVENT_CALLBACK(int e, IntPtr data); 

The data structure is also defined:

 [StructLayout(LayoutKind.Sequential)] public struct ECIO_INFO { public UInt32 ecio1; /*!< Primary scramble code */ public UInt32 ecio2; /*!< Received signal code power */ public UInt32 ecio3; /*!< Energy per chip per power density */ } 

In the C DLL, the function pointer is passed to CreateDataConnection () to update the status of the modem.

 int CreateDataConnection(EVENT_CALLBACK ecb) { . . fEventCallback = ecb; // Create a connection . . } 

After creating the connection, the DLL will call a callback function to update the state of the modem, such as EC / IO (ratio of received pilot energy).

Basically, when the ECIO changes, the callback function is called to pass the ECIO data to the C # application:

In the C DLL:

 void ProcessNotification(EVENT_CALLBACK fEventCallback) { ECIO_INFO ecio_info; ecio_info.ecio1 = ecio_info.ecio2 = ecio_info.ecio3 = 0; if(data.nNumOfCells>0) ecio_info.ecio1 = data.arCellInfo[0].nEcIo; if(data.nNumOfCells>1) ecio_info.ecio2 = data.arCellInfo[1].nEcIo; if(data.nNumOfCells>2) ecio_info.ecio3 = data.arCellInfo[2].nEcIo; if(data.nNumOfCells>0) fEventCallback(ME_RSCP_ECIO, &ecio_info); } 

In a C # application, the callback function is defined as:

 private void ModemEventCallback(int e, IntPtr data) { . . Modem.ECIO_INFO new_reinfo = new Modem.ECIO_INFO(); new_reinfo = (Modem.ECIO_INFO)Marshal.PtrToStructure( data, typeof(Modem.ECIO_INFO)); . . } 

Now a problem arises. When the program starts, everything is fine, the connection is created normally, and EC / IO is updated. but after working for several hours, the EC / IO update stops. After the test, I found that it was stopped when the callback was called:

 fEventCallback(ME_RSCP_ECIO, &ecio_info); 

I don’t know what went wrong. Probably passing the function pointer to the C # DLL is causing just the wrong way to do this, or is some kind of error similar to the code?

+4
source share
3 answers

Since the callback function is just a pointer to C / C ++, the callback parameter must be declared as IntPtr. Create the end of the EVENT_CALLBACK instance so that it remains alive the whole time your program starts. Use the Marshal.GetFunctionPointerForDelegate method to convert the delecate instance to IntPtr and pass the resulting IntPtr function to CreateDataConnection.

  [DllImport ("swmodem.dll", CallingConvention = CallingConvention.Winapi)]
       public static extern int CreateDataConnection (IntPtr callback);

 ...
 EVENT_CALLBACK c;
 c = new EVENT_CALLBACK (...);  // keep this alive!
 ...
 CreateDataConnection (Marshal.GetFunctionPointerForDelegate (c));
+3
source

try it

 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void EVENT_CALLBACK(int e, IntPtr data); 

He solved my problem.

+2
source

I think you should use GCHandl.Alloc with GCHandleType.Pinned , you tell gc that this object should remain in memory, although there can be no "roots" in the application that reference this object, and memory for this object cannot be compacted

+1
source

Source: https://habr.com/ru/post/1379111/


All Articles