4

I have an unmanaged DLL I am referencing in my project using [DLLImport], but am receiving odd results when I match method signatures.

Here is an example signature from the DLL:

DLLEXPORT unsigned long OpenPort(unsigned long  ulPort,
                                     unsigned long  ulBaudRate,
                                     unsigned long  ulByteSize,
                                     unsigned long  ulPartity,
                                     unsigned long  ulStopBits,
                                     unsigned long  ulFlowControl)

And here is my C# code to import the function:

[DllImport("C:/my.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern uint OpenPort(ulong ulPort, ulong ulBaudRate,
    ulong ulByteSize, ulong ulParity, ulong ulStopBits, ulong ulFlowControl);

Notice I declare this with a return type of uint, as when I attempt to use ulong I get unexpected results (long numbers usually that look a bit like memory addresses).

However, the function works and returns expected results if I use a return type of int/uint. Can anyone shed any light on this behaviour for me?

Thanks.

Alfie
  • 2,341
  • 2
  • 28
  • 45
  • 1
    What is sizeof(unsigned long) on your platform? It might be 4 bytes. ulong is always 8. – ta.speot.is Nov 04 '13 at 11:49
  • @ta.speot.is yep, you're right.. I didn't know the size of an unsigned long was inconsistent between C# and C++. Nothing confusing about that :) – Alfie Nov 04 '13 at 12:03
  • What's the reason for not using the build in serial port class? – Gusdor Nov 04 '13 at 12:08
  • @Gusdor the DLL is for third party hardware - that function is also responsible for initiating communication with the device etc. – Alfie Nov 04 '13 at 12:13
  • @Alfie David's answer has an example which is almost certainly what you want and answers the question more directly than mine. Would you mark him as the correct answer? – ta.speot.is Nov 04 '13 at 13:45
  • @ta.speot.is Thank you. I appreciate the dialog we had, and how you responded to my questioning. – David Heffernan Nov 04 '13 at 14:05
  • @DavidHeffernan I appreciate the time you took to question and discuss. – ta.speot.is Nov 04 '13 at 14:08

1 Answers1

3

I'm assuming that your target platform is Windows, based on the name of your library in the DllImport attribute. On Windows, the C++ long type (unsigned as well as signed, obviously) is 4 bytes wide, for both 32 and 64 bit. So, you need to declare your p/invoke using uint rather than ulong.

The correct declaration is:

[DllImport("C:/my.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern uint OpenPort(
    uint ulPort, 
    uint ulBaudRate,
    uint ulByteSize, 
    uint ulParity, 
    uint ulStopBits, 
    uint ulFlowControl
);

Now, if your target platform is other than Windows, then you'd need to know what unsigned long is on that platform to give specific advise.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • [This answer](http://stackoverflow.com/a/1764206/242520) is an excellent starting point for more information on the latter paragraph. – ta.speot.is Nov 04 '13 at 13:42