我在第三方C库周围创建C#P / invoke包装器时遇到问题。特别是,库有一个带签名的方法
int command(SomeHandle *handle, int commandNum, void *data, int datasize);
这是一个通配符方法,根据commandNum执行不同的操作。 data可以是指向任何东西的指针,如单个整数,char [],或某种结构(我的问题)。
我已经声明了包装器如下:
[DllImport("LIBRARY.DLL", EntryPoint = "command")]
public static extern int Command(IntPtr Handle, int CommandNum, [In, Out] IntPtr Data, int DataSize);
现在,当我使用操作码调用它来填充字节[]时,它可以工作:
//WORKS, Buffer contains "library 1.0" after the call
const int BUFFER_SIZE = 128;
byte[] Buffer = new byte[BUFFER_SIZE];
int BytesWritten = 0;
GCHandle BufferHandle = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
try
{
BytesWritten = Command(MyHandle, GET_VERSION, BufferHandle.AddrOfPinnedObject(), BUFFER_SIZE);
}
finally
{
BufferHandle.Free();
}
然而,当我尝试使用简单的结构时,无论我尝试什么,我都无法使其工作。结构看起来像这样:
public struct FormatInfoType
{
public int Format;
public IntPtr Name; //const char*
public IntPtr Extension; //const char*
}
这里我应该使用int(例如1)填充“Format”,然后调用“command(...)”意味着返回名称和扩展名字段
如果我传递此结构,代码将编译并正确运行,但结构中的值永远不会被修改。如果我将IntPtr更改为Strings或StringBuilders(并且我尝试了无数的MarshalAs属性),那么我无法将IntPtr添加到结构中,因为它变为非blittable并且GCHandle行抛出异常。
对此的任何帮助将不胜感激。
修改
我尝试了很多方法来调用带有结构的command(),但目前它看起来像这样:
FormatInfoType f = new FormatInfoType();
f.Format = 1;
f.Name = IntPtr.Zero;
f.Extension = IntPtr.Zero;
GCHandle fHandle = GCHandle.Alloc(f, GCHandleType.Pinned);
try
{
Command(MyHandle, GET_FORMAT_INFO, fHandle.AddrOfPinnedObject(), Marshal.SizeOf(f));
}
finally
{
fHandle.Free();
}
答案 0 :(得分:3)
您可以重载p / invoke签名,尝试:
[DllImport("LIBRARY.DLL", EntryPoint = "command")]
public static extern int Command(IntPtr Handle, int CommandNum, ref FormatInfoType Data, int DataSize);