【问题标题】:C# DllImport calling un-managed C++ function callbackC# DllImport 调用非托管 C++ 函数回调
【发布时间】:2019-12-27 18:15:24
【问题描述】:

您好,我有一个 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。我已经仔细检查了我的登录详细信息,一切都是正确的。如果有人有任何建议或示例,将不胜感激。

【问题讨论】:

  • 您是否尝试过使用[UnmanagedFunctionPointer(CallingConvention.StdCall)] 属性装饰回调的C# 声明?
  • 是的,我这样称呼它[DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall)]
  • 对不起,我说的是FUNLoginMsgCB委托声明
  • 感谢您的评论,它的行为似乎相同,没有变化。
  • @PavelAnikhouski 我想我错误地调用了IntPtr pUsr,也许我不明白。在 C# 中,IntPtr pUsr 等同于 void* pUsr,但在我的情况下,它应该是 this,表示形式...

标签: c# c++ function pointers dllimport


【解决方案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;
   }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-10-11
    • 2020-05-09
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-30
    相关资源
    最近更新 更多