我在Windows CE 6上编写了一个C#应用程序来监视3G调制解调器。该应用程序将调用C DLL中的函数来访问调制解调器。从C DLL调用C#回调函数时发生崩溃
在启动时,C#的应用程序将调用该函数创建一个新的连接:
[DllImport("swmodem.dll", CallingConvention = CallingConvention.Winapi)]
public static extern int CreateDataConnection(EVENT_CALLBACK callback);
的EVENT_CALLBACK定义为:
public delegate void EVENT_CALLBACK(int e, IntPtr data);
的数据结构也被定义:
[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 */
}
在C DLL中,函数指针在CreateDataConnection()中传递以用于调制解调器状态更新即
int CreateDataConnection(EVENT_CALLBACK ecb)
{
.
.
fEventCallback = ecb;
// Create a connection
.
.
}
创建连接之后,DLL将调用回调函数来更新调制解调器状态,例如EC/IO(所接收的导频能量之比)。
基本上,当ECIO变化,回调函数被调用,以通过ECIO数据到C#应用程序:
在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);
}
在C#应用程序,回调函数被定义为:
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));
.
.
}
现在问题出现了。程序启动时,一切正常,连接创建正常,EC/IO正在更新。但运行几个小时后,EC/IO更新会停止。测试后,我发现它时,停止回调调用:
fEventCallback(ME_RSCP_ECIO, &ecio_info);
我也不知道出了什么错在这里大概传递函数指针在C#DLL调用只是做不正确的方式,或者代码中埋藏了一些故障?
它被埋在我们看不见的代码中。委托对象可能正在收集垃圾。 GC无法从C代码中看到对它的引用。将对象存储在类或静态变量的字段中,以便GC可以看到它。 –
你会指针吗? –
同意@Hans同样发生在我身上,如果您不将它们存储在某处,代表将收集,GC无法跟踪传递给extern的引用C –