It is quite complex... Try this... It will probably go boom but then you can tell me how it did go boom and I can help you:
public class MyDllhelper
{
[StructLayout(LayoutKind.Sequential)]
public unsafe struct Info
{
public ushort port;
public ushort flag;
public fixed byte name[16];
public unsafe string Name
{
get
{
fixed (byte* ptr = name)
{
IntPtr ptr2 = (IntPtr)ptr;
return Marshal.PtrToStringAnsi(ptr2, 16).TrimEnd('\0');
}
}
set
{
fixed (byte* ptr = name)
{
IntPtr ptr2 = (IntPtr)ptr;
byte[] bytes = Encoding.Default.GetBytes(value);
int length = Math.Min(15, bytes.Length);
Marshal.Copy(bytes, 0, ptr2, length);
ptr[length] = 0;
}
}
}
}
public VoidRefInfoDelegate C { get; set; }
public VoidRefInfoDelegate Timeout { get; set; }
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void VoidRefInfoDelegate(ref Info info);
[DllImport("MyDLL", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr open(ref Info info, VoidRefInfoDelegate c, VoidRefInfoDelegate timeout);
public IntPtr Open(ref Info info, VoidRefInfoDelegate c, VoidRefInfoDelegate timeout)
{
C = c;
Timeout = timeout;
return open(ref info, C, Timeout);
}
}
Note that you'll have to do something like:
public void CMethod(ref MyDllhelper.Info info)
{
Console.WriteLine("C method called");
}
public void TimeoutMethod(ref MyDllhelper.Info info)
{
Console.WriteLine("Timeout method called");
}
var info = new MyDllhelper.Info();
info.Name = "012345678901234567890"; // Use Name, not name!
info.flag = 1;
info.port = 2;
var helper = new MyDllhelper();
IntPtr handle = helper.Open(ref info, CMethod, TimeoutMethod); // Use Open, not open!
You will need to compile the code with the Properties->Build->Allow unsafe code.
There are two or three interesting points in the code: the C array has been converted to a fixed
byte array. I've added a getter/setter Name
to handle the conversion from Ansi/ASCII to Unicode and back.
The C function has two callback methods (c
and timeout
). To use them, you need to "save" somewhere C#-side the delegates you'll use, because otherwise the garbage collector will free the delegates, and you'll receive an exception (see for example https://stackoverflow.com/a/6193914/613130). The C
and Timeout
properties are used for this.