C# DllImport calling un-managed C++ function callback
Asked Answered
T

1

0

Hi I have a C# WinForm app, I am able to call functions from the libnetclient.dll via DllImport like below:

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

I am then able to use the functions as normal such as below:

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

This callback occurs once the login function has completed.

My problem is with a callback function.

Inside the C++ netclient.h header file the pointer looks like this below:

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

I tried to call this in C# like such:

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;
   }
}

However no matter what I do the result is always 1. I have double checked my login details and all are correct. If anyone has any advice or examples it'll be greatly appreciated.

Towline answered 27/12, 2019 at 18:15 Comment(5)
Have you tried to decorate the C# declaration of callback using [UnmanagedFunctionPointer(CallingConvention.StdCall)] attribute?Dusen
yes I have called it like so [DllImport("libnetclient.dll", CallingConvention = CallingConvention.StdCall)]Towline
Sorry, I'm talking about FUNLoginMsgCB delegate declarationDusen
Thanks for the comment, it seems to behave the same, no change.Towline
@PavelAnikhouski I think I am calling the IntPtr pUsr incorrectly maybe I don't understand. In C# IntPtr pUsr is the equivalent to void* pUsr but in my case it was suppost to be this meaning the form...Towline
T
0

After a while I figured it out. I was using IntPtr pUsr incorrectly since it could be pointing to anything in my case it was pointing to this meaning the windows form.

Also all DLLs had to be called by CallingConvention = CallingConvention.StdCall some were left on CharSet = CharSet.Auto .....

This now works.

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;
   }
}
Towline answered 29/12, 2019 at 2:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.