C# DllImport 调用非托管 C++ 函数回调

C# DllImport calling un-managed C++ function callback

您好,我有一个 C# WinForm 应用程序,我可以通过 DllImport 从 libnetclient.dll 调用函数,如下所示:

[DllImport("libnetclient.dll", CharSet = CharSet.Auto)]
public static extern int NETCLIENT_Initialize(int bPriorRGB16 = 0);

然后我可以正常使用以下功能:

int ini = NETCLIENT_Initialize();
memoBox.AppendText("NETCLIENT_Initialize = " + ini.ToString()+Environment.NewLine);//append to box

此回调在登录功能完成后发生。

我的问题是回调函数。

在 C++ netclient.h 头文件中,指针如下所示:

NETCLIENT_API int API_CALL NETCLIENT_RegLoginMsg(void* pUsr, void (CALLBACK * FUNLoginMsgCB)(int nMsg, void * pUsr));

我试着在 C# 中这样调用它:

public delegate void FUNLoginMsgCB(int nMsg, IntPtr pUsr);
....
....
[DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int NETCLIENT_RegLoginMsg(IntPtr pUsr, FUNLoginMsgCB _callback);

private void loginbutton_Click(object sender, EventArgs e)
{
  var _callback = new FUNLoginMsgCB(DoLoginMsgCB);
  NETCLIENT_RegLoginMsg(this.Handle, _callback);//call the callback function
}

private static void DoLoginMsgCB(int nMsg, IntPtr pUsr)
 {
   switch (nMsg)//switch shows result after login function called
    {
      case 0:
          MessageBox.Show("LOGIN_SUC");
          break;
      case 1:
          MessageBox.Show("LOGIN_FAILED");
          break;
      case 2:
          MessageBox.Show("LOGIN_DISCNT");
          break;
      case 3:
          MessageBox.Show("LOGIN_NAME_ERR");
          break;
      default:
          MessageBox.Show("DEFAULT");               
          break;
   }
}

但是无论我做什么,结果总是 1。我仔细检查了我的登录详细信息,一切都是正确的。如果有人有任何建议或示例,我们将不胜感激。

过了一会儿我想通了。我使用 IntPtr pUsr 不正确,因为在我的例子中它可能指向任何东西它指向 this 意思是 windows 形式。

此外,所有 DLLs 都必须由 CallingConvention = CallingConvention.StdCall 调用,有些留在 CharSet = CharSet.Auto .....

现在可以使用了。

public delegate void FUNLoginMsgCB(int nMsg, Form1 form1);
....
....
[DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int NETCLIENT_RegLoginMsg(Form1 form1, FUNLoginMsgCB _callback);

private void loginbutton_Click(object sender, EventArgs e)
{
  var _callback = new FUNLoginMsgCB(DoLoginMsgCB);
  NETCLIENT_RegLoginMsg(this, _callback);//call the callback function
}

private static void DoLoginMsgCB(int nMsg, Form1 form1)
 {
   switch (nMsg)//switch shows result after login function called
    {
      case 0:
          MessageBox.Show("LOGIN_SUC");
          break;
      case 1:
          MessageBox.Show("LOGIN_FAILED");
          break;
      case 2:
          MessageBox.Show("LOGIN_DISCNT");
          break;
      case 3:
          MessageBox.Show("LOGIN_NAME_ERR");
          break;
      default:
          MessageBox.Show("DEFAULT");               
          break;
   }
}