如何解決C#調(diào)用C/C++DLL回調(diào)函數(shù)導(dǎo)致內(nèi)存崩潰的問題-創(chuàng)新互聯(lián)

問題描述:

成都創(chuàng)新互聯(lián)不只是一家網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司;我們對營銷、技術(shù)、服務(wù)都有自己獨(dú)特見解,公司采取“創(chuàng)意+綜合+營銷”一體化的方式為您提供更專業(yè)的服務(wù)!我們經(jīng)歷的每一步也許不一定是最完美的,但每一步都有值得深思的意義。我們珍視每一份信任,關(guān)注我們的做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)質(zhì)量和服務(wù)品質(zhì),在得到用戶滿意的同時(shí),也能得到同行業(yè)的專業(yè)認(rèn)可,能夠?yàn)樾袠I(yè)創(chuàng)新發(fā)展助力。未來將繼續(xù)專注于技術(shù)創(chuàng)新,服務(wù)升級,滿足企業(yè)一站式成都營銷網(wǎng)站建設(shè)需求,讓再小的品牌網(wǎng)站設(shè)計(jì)也能產(chǎn)生價(jià)值!

1. C/C++ 寫的 DLL,其中有個(gè)方法(如MethodA)有的參數(shù)是回調(diào)函數(shù)。

2. C# 調(diào)用 DLL的方法MethodA,將自己的一個(gè)內(nèi)部方法(InnerMethod)作為回調(diào)函數(shù)的地址傳遞過去。

3. 當(dāng) InnerMethod 被觸發(fā)時(shí),往往第一次能成功,再次觸發(fā)時(shí)就會崩潰,報(bào)的錯(cuò)誤為非法內(nèi)存訪問之類。

碰到以上錯(cuò)誤,估計(jì)你的大腦也會像內(nèi)存一樣:奔潰??赡軙L試各種辦法:修改 C/C++ 代碼,將方法加上 _stdcall;修改 C# 代碼,調(diào)整調(diào)用約定;修改 InnerMethod,增加各種調(diào)試,改用臨時(shí)變量,改用全局變量,只做計(jì)算,不訪問其它資源。。。最后呢,還是奔潰。

我當(dāng)時(shí)就被這個(gè)問題折磨了好幾天,而同事的 QT 調(diào)用 DLL 卻正常,這說明問題還是出在?C# 上。后來經(jīng)過多方查找,發(fā)現(xiàn)是 C# 的GC的問題,是GC把C#內(nèi)的回調(diào)函數(shù)回收了,當(dāng)下次DLL再次調(diào)用這個(gè)函數(shù)時(shí),就會觸發(fā)非法內(nèi)存訪問的錯(cuò)誤。

如何修復(fù)呢?強(qiáng)制GC保留它,等到最后才回收。一般,出問題的的代碼如下:

///


/// 調(diào)用 DLL 的方法(參數(shù)為回調(diào)函數(shù)地址)
///

private void CallDll()
{
?DllMethodA(OnCallBack); ? ? ? ? ? ?
}

///


/// 給 DLL 的回調(diào)函數(shù)
///

///
private void OnCallBack(int retValue)
{
?Console.WriteLine($@"the return value from the dll is {retValue}");
}

將代碼修改如下:

// 聲明委托,
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void MethodCallbackEvent(int i);
private static MethodCallbackEvent _callbackFunc = null;
private static GCHandle _gcHandle = new GCHandle();

///


/// 調(diào)用 DLL 的方法(參數(shù)為回調(diào)函數(shù)地址)
///

private void CallDll()
{
?// 讓 GC 保留,不回收這個(gè)回調(diào)函數(shù)
?_callbackFunc = new MethodCallbackEvent(OnCallBack);
?_gcHandle = GCHandle.Alloc(_callbackFunc);

?DllMethodA(_callbackFunc);
}

///


/// 給 DLL 的回調(diào)函數(shù)
///

///
private void OnCallBack(int retValue)
{
?Console.WriteLine($@"the return value from the dll is {retValue}");
}

///


/// 增加一個(gè)釋放的方法,在合適的時(shí)候調(diào)用
///

private void ReleaseCallback()
{
?if (_gcHandle.IsAllocated) { _gcHandle.Free(); }
}

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧

網(wǎng)站名稱:如何解決C#調(diào)用C/C++DLL回調(diào)函數(shù)導(dǎo)致內(nèi)存崩潰的問題-創(chuàng)新互聯(lián)
網(wǎng)站地址:http://www.bm7419.com/article18/ihddp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)網(wǎng)站維護(hù)、全網(wǎng)營銷推廣、營銷型網(wǎng)站建設(shè)、網(wǎng)站收錄網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

營銷型網(wǎng)站建設(shè)