我在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 –