tags:

views:

143

answers:

2

I am using C# in Mono and I'm trying to use pinvoke to call a Linux shared library.

The c# call is defined as:

   [DllImport("libaiousb")]
   extern static ulong AIOUSB_Init();

The Linux function is defined as follows:

  unsigned long AIOUSB_Init() {
       return(0);
  }

The compile command for the Linux code is:

gcc -ggdb -std=gnu99 -D_GNU_SOURCE -c -Wall -pthread -fPIC
      -I/usr/include/libusb-1.0  AIOUSB_Core.c -o AIOUSB_Core.dbg.o

I can call the function ok but the return result is bonkers. It should be 0 but I'm getting some huge mangled number.

I've put printf's in the Linux code just before the function value is returned and it is correct.

One thing I have noticed that is a little weird is that the printf should occur before the function returns. However, I see the function return to C# and then the c# prints the return result and finally the printf result is displayed.

+1  A: 

You're probably running that on a system where C unsigned long is 32-bits. C# unsigned long is 64 bits. If you want to make sure the return value is a 64-bits unsigned long, include stdint.h and return an uint64_t from AIOUSB_Init().

Gonzalo
You were so right! Thank you very much! You have no idea how long I beat my head on this. I thought all the current pentium processors used 32 bit word size so an unsigned long should be 64 bits?I will look for a secure way to use paypal to send you a small token of my appreciation!
jyh
You're welcome. No need for PayPal. stackoverflow is about help in exchange for upvotes and accepting answers ;-)
Gonzalo
An unsigned long is only 64-bits on 64-bit platforms (and under 64-bit operating systems), otherwise it's 32-bits.
jonp
For additional details, see my answer at: http://stackoverflow.com/questions/1753413/parameters-passed-by-reference-come-back-garbage-using-p-invoke
jonp
+1  A: 

From here:

An unsigned long can hold all the values between 0 and ULONG_MAX inclusive. ULONG_MAX must be at least 4294967295. The long types must contain at least 32 bits to hold the required range of values.

For this reason a C unsigned long is usually translated to a .NET UInt32:

[DllImport("libaiousb")]
extern static uint AIOUSB_Init();
dtb