Bare bones: we can always do this
static extern int GetVersion(IntPtr ver, ref UIntPtr size );
I would never write this because I don't like what this generates for A->W conversion:
static extern int GetVersion([MarshalAs(UnmanagedType.LPStr)] StringBuilder ver, ref UIntPtr size);
Also, if this is a true counted string, the P/Invoke code doesn't work as it wants a 0 after the end.
I would normally write
static extern int GetVersion( byte[] ver, ref UIntPtr size );
in which you must first create ver
at the maximum size. You can then convert ver
to string using the stuff in System.Text.Encoding
. GetVersion()
almost certainly passes a constant back, so you can hardcode the correct encoding (probably ASCII anyway).
There's a pretty good chance you're missing [DllImport(..., CallingConvention=CallingConvention.Cdecl)]
causing you some memory corruption, but I can't actually tell.
Mistake: don't use ulong
for size_t
. size_t
is UIntPtr
on all supported platforms.
Comment suggests a completely different signature GetDevInfo(int Index, DevInfo * pdevInfo);
This is a different thing altogether and there's clearly one best choice:
const int IDLength = 100;
[StructLayout(LayoutKind.Sequential)]
struct DeviceInfo {
[MarshalAs(UnmanagedType.ByValArray, SizeConst = IDLength)]
byte[] ID;
}
static extern /* I don't know what's here because missing from comment */
GetDevInfo(int index, ref strcut DeviceInfo info);
string GetInfo(int index)
{
var info = new DeviceInfo();
info.ID = new byte[IDLength];
GetDevInfo(info.ID);
return System.Text.Encoding.ASCII.GetString(info.ID, 0, strlen(info.ID));
}
int strlen(byte[] bytes)
{
int i;
for (i = 0; i < bytes.Length && bytes[i] != 0; i++)
;
return i;
}
````