Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
P/Invoke C#struct,并将字符串连接到C void*_C#_String_Struct_Pinvoke_Void - Fatal编程技术网

P/Invoke C#struct,并将字符串连接到C void*

P/Invoke C#struct,并将字符串连接到C void*,c#,string,struct,pinvoke,void,C#,String,Struct,Pinvoke,Void,我在围绕第三方C库创建C#p/invoke包装时遇到问题。特别是,库中有一个带有签名的方法 int command(SomeHandle *handle, int commandNum, void *data, int datasize); 它是一个通配符方法,根据commandNum执行不同的操作。数据可以是指向任何对象的指针,如单个整数、字符[]或某种结构(我的问题) 我已声明包装如下: [DllImport("LIBRARY.DLL", EntryPoint = "command")]

我在围绕第三方C库创建C#p/invoke包装时遇到问题。特别是,库中有一个带有签名的方法

int command(SomeHandle *handle, int commandNum, void *data, int datasize);
它是一个通配符方法,根据commandNum执行不同的操作。数据可以是指向任何对象的指针,如单个整数、字符[]或某种结构(我的问题)

我已声明包装如下:


[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* 
}

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();
}
在这里,我应该用int(比如1)填充“Format”,然后调用“command(…)”将返回名称和扩展字段

如果我传递这个结构,代码将正确编译和运行,但结构中的值永远不会被修改。如果我将IntPtr更改为Strings或StringBuilders(并且我尝试了大量marshallas属性),那么我无法将IntPtr转换为struct,因为它变得不可blittable,并且GCHandle行抛出异常

在此方面的任何帮助都将不胜感激

编辑:

我尝试了许多方法来使用该结构调用command(),但目前看起来是这样的:


public struct FormatInfoType
{
    public int Format;
    public IntPtr Name; //const char* 
    public IntPtr Extension; //const char* 
}

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();
}

您可以重载p/invoke签名,请尝试:

[DllImport("LIBRARY.DLL", EntryPoint = "command")]
public static extern int Command(IntPtr Handle, int CommandNum, ref FormatInfoType Data, int DataSize);

您能否显示将
FormatInfoType
封送到函数中的代码?您是否尝试过使用
[MarshalAs(UnmanagedType.LPStr)]
属性标记的字符串?@Richard:我刚刚更新了问题@Ben,是的,我已经试过了,但是结构变得不可blittable,我无法得到一个IntPtr传递给命令(..)调用。我猜问题是我无法在托管代码中分配该结构中的字符串缓冲区,我必须依靠“command()”来完成,也许托管代码不喜欢这样。