日期:2014-05-17  浏览次数:21039 次

C#调用DLL(结构体中包含回调函数)
C# 中调用dll的回调函数,该回调函数是在结构体中,
但是c#中调用产生crash了..感觉是因为调用约定的问题.vc默认是Cdecl,而.net的delegate 是使用stdcall.请问如果才能正常调用.
extern "C" __declspec( dllexport ) BOOL __stdcall Test(FILEWRITE* pFile)
{
CFileWrite* pStreamWrite = NULL;
pStreamWrite = new CFileWrite;
pStreamWrite->Init( pFile );
while (1)
{
pStreamWrite->WriteBlock("1",1);
}
return TRUE;
}



//以下是该结构体说明.
struct FILEWRITE
{
int (*WriteBlock)(FILEWRITE* pThis, const void* buf, unsigned long size);
};

class CFileWrite
{
public:
void Init(FILEWRITE * pFileWriteStruct);
virtual BOOL WriteBlock(const void* pData, DWORD size);
protected:
FILEWRITE* m_pFileWriteStruct;
private:
};

void CFileWrite::Init(FILEWRITE * pFileWriteStruct)
{
m_pFileWriteStruct = pFileWriteStruct;

}
BOOL CFileWrite::WriteBlock(const void* pData, DWORD size)
{
m_pFileWriteStruct->WriteBlock(m_pFileWriteStruct,pData,size);
return TRUE;
}




.net 中调用
  [DllImport("DLLTest2.dll",CallingConvention = CallingConvention.StdCall)]
  public static extern string Test(ref FPDF_FILEWRITE pFilewriter);

  public delegate int WriteBlock(ref FPDF_FILEWRITE pThis, byte[] pData, long size);

  public struct FPDF_FILEWRITE
  {
  public WriteBlock wb;
  }

  public static int MyDelegateFunc(ref FPDF_FILEWRITE pThis, byte[] pData, long size)
  {
  return 1;
  }

  private void button1_Click(object sender, EventArgs e)
  {
  FPDF_FILEWRITE pFile = new FPDF_FILEWRITE();
  pFile.wb = new WriteBlock(MyDelegateFunc);
  Test(ref pFile);
  }



------解决方案--------------------
pFile.wb = new WriteBlock(MyDelegateFunc);

是简化写法。这里的MyDelegateFunc并不是函数,而是委托的简化写法。

等效为

pFile.wb = new WriteBlock(new WriteBlock(MyDelegateFunc));

这里的new WriteBlock(MyDelegateFunc)是个函数内的临时变量。离开函数,不知道什么时候,合适的时候就被释放了。你可以吧这个委托声明到外面,例如

private WriteBlock callback_procude = null;
callback_procude = new WriteBlock(MyDelegateFunc);
pFile.wb = new WriteBlock(callback_procude);

这样可能就可以了。

理论上是这样的。