Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PInvoke marshalling of integers returning incorrect result

I have a very simple function in an unmanaged DLL, but I'm not getting the correct return value back from it.

I can confirm that the general PInvoke mechanism is working with one function in my C DLL:

/* Return an integer */
extern "C" __declspec(dllexport) long get_num()
{
    return 42;
}

I call the above unmanaged entry point like so from C# .NET:

[DllImport("My_C_DLL.dll")]
extern static long get_num();
// ...
long ans = get_num();
Console.WriteLine("The answer is {0}.", ans);

This works fine, but passing marshalled parameters to another function in the DLL returns a wrong result:

/* Add two integers */
extern "C" __declspec(dllexport) long add_num(long a, long b)
{
    long sum = a + b;

    return sum;
}

Called from C# as:

[DllImport("My_C_DLL.dll")]
extern static long add_num(long a, long b);

long a = 6, b = 12;
long sum = add_num(a, b);
Console.WriteLine("The answer is {0}.", sum);

This gives me back a result of "6", or whatever I set the input value of a to be.

I'm guessing that some incorrect marshalling of the input values is messing up the call stack, resulting in the bad return value, but where is the error?

like image 984
Buggieboy Avatar asked Nov 30 '25 10:11

Buggieboy


2 Answers

Two problems here. First of all C# long does not match C long. On Windows, C long is 32 bits. Use int in your C# code to match up with your C long.

The other problem is that the calling conventions probably don't match. You most likely have cdecl in your C DLL but the C# default is stdcall. Fix this by changing your p/invoke.

[DllImport("My_C_DLL.dll", CallingConvention=CallingConvention.Cdecl)]
like image 54
David Heffernan Avatar answered Dec 03 '25 01:12

David Heffernan


You might have a problem with the managed part defining long as a 64-bit integer, while your C compiler defining it as 32-bit integer.

You can either change long to int in your C# code, change long to int64_t in your C code, or force the 32-bit marshalling using MarshalAs(UnmanagedType.I4) (force marshalling only if all other ideas fail)

like image 20
user1071136 Avatar answered Dec 02 '25 23:12

user1071136



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!