Reputation: 1329
I need to export function from C DLL. Here is example that I have written
typedef struct tag_struct {
unsigned char first;
unsigned char second;
} st_struct;
__declspec(dllexport) unsigned char Func( st_struct *ptr )
{
return ptr->first + ptr->second;
}
Here is C# code that I'm using to import described above function.
using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace ImportTest
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public class st_struct
{
public byte first;
public byte second;
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
st_struct x = new st_struct();
x.first = 1;
x.second = 2;
byte result = Func(ref x);
}
[DllImport("MarshalTest.dll")]
protected static extern byte Func(ref st_struct inputs);
}
}
My problem is that return value of Func is not 3 as it should be (1 + 2).
I am using debugger to see values inside DLL - they are different (not 1 and 2 that I provided).
Function returns proper value whan I change C# code like that:
public Form1()
{
InitializeComponent();
st_struct x = new st_struct();
x.first = 1;
x.second = 2;
byte result = Func(x);
}
[DllImport("MarshalTest.dll")]
protected static extern byte Func(st_struct inputs);
Problem disappears when I remove ref. But I don't understand why.
Could you please explain that?
Upvotes: 2
Views: 4127
Reputation: 5515
As @kennyzx mentions, since your st_struct
is a class, it is already a reference type and will be passed as a pointer. I suspect throwing a ref
onto that will give you a double pointer, which doesn't make much sense when mixing managed and unmanaged code. The marshaller can possibly handle that and create a new object for you if the pointer changes, but it seems like a sketchy thing to do.
So, when passing the class without ref
, it works as expected (the C code gets a pointer). If you change it to a struct
, passing it without ref
should pass it on the stack and passing it with ref
will pass it as a pointer.
Using struct
seems like the obvious choice in your case, as it can be passed directly (the CLR just needs to pin it and pass a pointer). Using class
I suspect will involve more marshalling.
Upvotes: 2
Reputation: 13003
You might be thinking that the ref
keyword is required in order to passing parameter by reference
. But since st_struct
is defined as a reference type (class is reference type), so the parameter is passed by reference, not by value. You don't need the ref
keyword.
If st_struct
were defined as struct
, you may find it work when you use the ref
keyword.
Upvotes: 2