C#调用C++的dll,PInvoke问题和回调函数抛出异常access violation
不磨叽,直接上代码。
C++动态库中函数定义
#ifndef _AUDIOSYSSDK_H #define _AUDIOSYSSDK_H typedef void PlayResFunc(void *powner,int filestate, int playlen); extern "C" { int _stdcall Audio_OpenChannel(char *pLocalAddr,PlayResFunc *pFun,void *powner); int _stdcall Audio_CloseChannel(int idx); }
在C#中的调用的代码
#warning 这个委托一定要标记为Cdecl /* 这个委托一定要标记为[System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.Cdecl)], * 否则在C#调用时在回调函数执行一次后会退出或会抛出异常Access violation */ /// Return Type: void ///powner: void* ///filestate: int ///playlen: int [System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute(System.Runtime.InteropServices.CallingConvention.Cdecl)] public delegate void PlayResFunc(System.IntPtr powner, int filestate, int playlen);
public class AudioSysSdkHelper { [System.Runtime.InteropServices.DllImportAttribute("AudioSysSDK.dll", EntryPoint = "Audio_OpenChannel", CallingConvention = CallingConvention.StdCall)] public static extern int Audio_OpenChannel(string pLocalAddr,PlayResFunc pFun,System.IntPtr powner); }
winform程序调用的代码
public PlayResFunc PlayResFuncObj = null; private void button3_Audio_OpenChannel_Click(object sender, EventArgs e) { string pLocalAddr = "192.168.7.22"; PlayResFuncObj =PlayRes; channelIndex = AudioSysSdkHelper.Audio_OpenChannel(pLocalAddr, PlayResFuncObj, IntPtr.Zero); if (channelIndex >= 0) { SetTextShow(string.Format("打开通道成功,通道号{0}", channelIndex)); } else { SetTextShow(string.Format("打开通道失败,返回值{0}", channelIndex)); } }
public void PlayRes(IntPtr powner, int filestate, int playlen) { try { int groupid = (int)powner; ePlayStatus state = (ePlayStatus)filestate; switch (state) { case ePlayStatus.PS_PlayDone: SetTextShow("播放完毕"); //System.Diagnostics.Trace.WriteLine("播放完毕"); break; case ePlayStatus.PS_PlayPause: SetTextShow("播放暂停"); //System.Diagnostics.Trace.WriteLine("播放暂停"); break; case ePlayStatus.PS_PlayStatus: SetTextShow(string.Format("播放了百分之{0}", playlen)); //System.Diagnostics.Trace.WriteLine(string.Format("播放了百分之{0}", playlen)); break; } } catch(Exception ex) { throw ex; } }
这个问题耗了我一天半的时间,这里Mark一下,备忘。
C#调用C++动态库的坑还是很多的。童鞋们注意自身安全!