void WINAPI (DLL_EXP SetMessageProcessCallback)(void* pUserObject_, void (*pfUserMessageProcessFunc_)(void*,AMC_MESG*));
这是c++ dll 的一个函数,第二个参数是一个回调函数, 而这个回调函数的第二个参数是一个类的实例,请问这样的一个函数如何用c#写出来,多谢。
下面是我写的:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void SetMessageCallback(IntPtr sender, [In, Out] AMC_MESG _amc); [DllImport(Constant.Dllname_amc, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static void SetMessageProcessCallback(IntPtr pUserObject_, SetMessageCallback pfUserMessageProcessFunc_); public void ProprioWare_Load(object sender, EventArgs e)
{
callback1 = new SetMessageCallback(MesgProcessCallback);
GC.Collect();
GC.WaitForPendingFinalizers();
SetMessageProcessCallback(this.Handle, callback1);
GC.KeepAlive(callback1);
}
public void MesgProcessCallback(IntPtr sender, [In,Out] AMC_MESG amc)
{ }[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class AMC_MESG
{
}
这样会报一个错误:Attempted to read or write protected memory. This is often an indication
这是c++ dll 的一个函数,第二个参数是一个回调函数, 而这个回调函数的第二个参数是一个类的实例,请问这样的一个函数如何用c#写出来,多谢。
下面是我写的:
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void SetMessageCallback(IntPtr sender, [In, Out] AMC_MESG _amc); [DllImport(Constant.Dllname_amc, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static void SetMessageProcessCallback(IntPtr pUserObject_, SetMessageCallback pfUserMessageProcessFunc_); public void ProprioWare_Load(object sender, EventArgs e)
{
callback1 = new SetMessageCallback(MesgProcessCallback);
GC.Collect();
GC.WaitForPendingFinalizers();
SetMessageProcessCallback(this.Handle, callback1);
GC.KeepAlive(callback1);
}
public void MesgProcessCallback(IntPtr sender, [In,Out] AMC_MESG amc)
{ }[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class AMC_MESG
{
}
这样会报一个错误:Attempted to read or write protected memory. This is often an indication
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class AMC_MESG
{
private ushort usID;
private byte ucSize;
private byte ucRawMesgSize;
private byte[] aucRawMesg = new byte[Constant.AMCMESG_MAX_SIZE];
private byte ucScrDest; public ushort GetMesgID() { return usID; }
public byte GetMesgScrDest() { return ucScrDest; }
public byte GetMesgSize() { return ucSize; }
public byte[] GetMesgData()
{
byte[] tmp = new byte[aucRawMesg.Length];
Buffer.BlockCopy(aucRawMesg, Convert.ToInt32(Constant.AMCMESG_DATA_OFFSET), tmp, 0, tmp.Length);
return tmp;
}
public byte[] GetRawMesgData() { return aucRawMesg; }
public byte GetRawMesgSize() { return ucRawMesgSize; }
public void SetMesgID(ushort usID_) { usID = usID_; }
public void SetMesgScrDest(byte ucScrDest_) { ucScrDest = ucScrDest_; }
public void SetMesgSize(byte ucSize_) { ucSize = ucSize_; } void SetMesgData(ushort usID_, byte ucScrDest_, byte[] pucData_, byte ucSize_)
{
SetMesgID(usID_);
SetMesgScrDest(ucScrDest_);
SetMesgSize(ucSize_);
Buffer.BlockCopy(pucData_, 0, aucRawMesg, Convert.ToInt32(Constant.AMCMESG_DATA_OFFSET), Convert.ToInt32(ucSize_));
//memcpy(aucRawMesg + AMCMESG_DATA_OFFSET, pucData_, ucSize_);
} void SetRawMesgData(byte[] pucRawMesg_, byte ucRawMesgSize_)
{
//memcpy(aucRawMesg,pucRawMesg_,ucRawMesgSize_);
Array.Copy(pucRawMesg_, aucRawMesg, Convert.ToInt32(ucRawMesgSize_));
ucRawMesgSize = ucRawMesgSize_;
} //public void operator=( ref AMC rhs)
//{
// this.ucRawMesgSize = rhs.ucRawMesgSize;
// this.ucSize = rhs.ucSize;
// //memcpy(this.aucRawMesg,rhs.aucRawMesg,this.ucRawMesgSize);
// Buffer.BlockCopy(rhs.aucRawMesg,0,this.aucRawMesg,0,this.ucRawMesgSize);
// this.SetMesgID(rhs.usID);
// this.ucScrDest = rhs.ucScrDest;
//}
}
参考
http://topic.csdn.net/u/20071010/13/5197506d-1bcb-45b9-b9e1-5ad3eb2ac9ec.html
http://topic.csdn.net/u/20071126/14/4b94abfb-4933-4a5f-96f2-2f81f4eeec69.html
class AMC_MESG
{
public:
inline USHORT GetMesgID() { return usID; }
inline UCHAR GetMesgScrDest() {return ucScrDest;}
inline UCHAR GetMesgSize() { return ucSize; }
inline UCHAR* GetMesgData(){ return aucRawMesg + AMCMESG_DATA_OFFSET; }
inline UCHAR* GetRawMesgData() { return aucRawMesg; }
inline UCHAR GetRawMesgSize() { return ucRawMesgSize; }
inline void SetMesgID(USHORT usID_) { usID = usID_; }
inline void SetMesgScrDest(UCHAR ucScrDest_) { ucScrDest = ucScrDest_; }
inline void SetMesgSize(UCHAR ucSize_) { ucSize = ucSize_; } void SetMesgData(USHORT usID_, UCHAR ucScrDest_, UCHAR *pucData_, UCHAR ucSize_)
{
SetMesgID(usID_);
SetMesgScrDest(ucScrDest_);
SetMesgSize(ucSize_);
memcpy(aucRawMesg + AMCMESG_DATA_OFFSET, pucData_, ucSize_);
} void SetRawMesgData(UCHAR *pucRawMesg_,UCHAR ucRawMesgSize_)
{
memcpy(aucRawMesg,pucRawMesg_,ucRawMesgSize_);
ucRawMesgSize = ucRawMesgSize_;
} void operator= (const AMC_MESG &rhs)
{
this->ucRawMesgSize = rhs.ucRawMesgSize;
this->ucSize = rhs.ucSize;
memcpy(this->aucRawMesg,rhs.aucRawMesg,this->ucRawMesgSize);
this->SetMesgID(rhs.usID);
this->ucScrDest = rhs.ucScrDest;
}private:
USHORT usID;
UCHAR ucSize;
UCHAR ucRawMesgSize;
UCHAR aucRawMesg[AMCMESG_MAX_SIZE];
UCHAR ucScrDest;
};
1、不需要完成C#的方法实现。
如果AMC_MESG没有虚函数的话,C++中的方法调用是编译时就链接到固定地址了,C++不会调用你的C#实现的。2、如果AMC_MESG有虚函数的话,你最好放弃C#交互,或另写一个C++的DLL当中转了。
答案如下:
调整AMC_MESG类:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class AMC_MESG
{
[MarshalAs(UnmanagedType.U2)]
public ushort usID;
[MarshalAs(UnmanagedType.I1)]
public byte ucSize;
[MarshalAs(UnmanagedType.I1)]
public byte ucRawMesgSize;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = Constant.AMCMESG_MAX_SIZE)]
public byte[] aucRawMesg = new byte[Constant.AMCMESG_MAX_SIZE];
[MarshalAs(UnmanagedType.I1)]
public byte ucScrDest;
}
这样就可以将AMC_MESG的实例作为callback的参数传入了