0

I am totally new to C++ programming. I need to call a C++ function from C#.

C++ function is:

BOOL Usb_Init(HWND hwnd);

I've tried:

[DllImport("UsbComm.dll",  SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool Usb_Init( out IntPtr hwnd);

I got the Error message:

PInvoke signature does not match the unmanaged target signature.

How to call the above C++ method?

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Justin CI
  • 2,693
  • 1
  • 16
  • 34

3 Answers3

1

BOOL is defined as int in <windef.h>

You'll need to use int in the export declaration in C#. Reminder: a value of 0 equals false; anything else is true.

public static extern int Usb_Init(out IntPtr hwnd);

But also, your calling convention could also be wrong. Try each enum of CallingConvention

EDIT: The working signature is

[DllImport("UsbComm.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
public static extern int Usb_Init(out IntPtr hwnd);
Michael Stum
  • 177,530
  • 117
  • 400
  • 535
Nick Strupat
  • 4,928
  • 4
  • 44
  • 56
  • I tried DllImport("UsbComm.dll")] public static extern int Usb_Init(out IntPtr hwnd); also called method IntPtr hwnd = new IntPtr(0); var res = Usb_Init(out hwnd); signature does not match error occured – Justin CI Feb 03 '15 at 06:04
  • 1
    [DllImport("UsbComm.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] public static extern int Usb_Init(out IntPtr hwnd); – Justin CI Feb 03 '15 at 06:16
  • You've accepted this answer but it is not correct. The `hwnd` parameter is passed incorrectly. And there's no need to make the return type `int`. You can use `bool` in C# which is marshalled as the Windows `BOOL` type. – David Heffernan Feb 03 '15 at 09:04
  • @David Heffernan: int value is also working fine.Which meets my needs.So i accept the answer. – Justin CI Feb 03 '15 at 09:25
  • `int` will work but it's needlessly complex. I'm surprised you ignore the mistake in the `hwnd` parameter. Hard to understand why you ask the question if you aren't prepared to listen to answers. – David Heffernan Feb 03 '15 at 09:33
  • @David Heffernan: Sorry.I just looked out for a working solution. – Justin CI Feb 03 '15 at 09:38
  • I'm here to tell you that you will not find one in this answer. `out IntPtr` does not match `HWND`. Anyway, I've said my peace. I'm not going to try to force you to listen to me. I'll gladly help you if you wish to be helped. – David Heffernan Feb 03 '15 at 09:41
  • @David Heffernan: Thank you for your help.Can you please provide me C# signature for:BOOL Usb_IsConnectionValid(DWORD dwUsbDeviceNumber); – Justin CI Feb 03 '15 at 09:48
  • `DWORD` is an unsigned 32 bit integer. That's `uint` in C#. The parameter would therefore be `uint dwUsbDeviceNumber`. Everything else is just the same as the function in this question. – David Heffernan Feb 03 '15 at 09:52
  • @David Heffernan:It always returns false – Justin CI Feb 03 '15 at 09:53
  • I guess something is wrong then. Hard to know what exactly. – David Heffernan Feb 03 '15 at 09:55
  • @David Heffernan: Can you please provide me C# signature for BOOL Usb_GetDevicesList(int &iNbDevices, char aszDeviceName[][128]); – Justin CI Feb 03 '15 at 11:57
  • 1
    That's a new question. And quite a tricky one. You probably need to include more information. You cannot ask questions in comments. However, the question has been asked here: http://stackoverflow.com/questions/28293025/calling-c-method-in-c-sharp I do think that you need to step back a little and read the help content for the SO site. You would get a lot more out of the site if you had a clearer understanding of how to ask good questions. – David Heffernan Feb 03 '15 at 12:01
  • @ David Heffernan: Thank you very much – Justin CI Feb 03 '15 at 12:04
1

I see the following mistakes in the code in the question:

  1. The C++ code uses cdecl and the C# code uses stdcall. That does not match.
  2. The C++ code is passed an HWND by value. The C# code has an IntPtr passed as an out parameter. That does not match.
  3. There are multiple spurious arguments to the DllImport attribute.

The correct C# declaration is:

[DllImport("UsbComm.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool Usb_Init(IntPtr hwnd);

You could set ExactSpelling to true but I see no compelling reason to do so. Feel free to add that if you prefer. There's no point in specifying CharSet since there is no text involved. And SetLastError = true is probably a mistake. It's unlikely in my judgement that the unmanaged function calls SetLastError. My expectation is that you added SetLastError = true whilst trying to get rid of the error.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

C++ code: Make sure definition of Usb_Init should look as shown below:

    extern "C" __declspec(dllexport) BOOL __stdcall  Usb_Init(HWND hwnd)
    {
       return TRUE;
    }

C# code:

using System;
using System.Runtime.InteropServices;

namespace Win32DllClient
{

    class Program
    {
        [DllImport("UsbComm.dll", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        public static extern bool Usb_Init(out IntPtr hwnd);
        static void Main(string[] args)
        {
               IntPtr hwnd = new IntPtr(0);
               var ret = Usb_Init(out hwnd);
        }
    }
}
Vinkal
  • 2,964
  • 1
  • 19
  • 19