使用 char** 调用 cdecl 约定
Pinvoke cdecl convention with char**
总结:
我正在尝试使用带有 cdecl 调用约定 的 C++ dll 所有 运行 都很好,除非我得到这个方法签名:
int SaveToBuffer( char **buf, int *buf_size );
根据我的阅读,我应该这样使用它:
[DllImport("entry.dll",
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "SaveToBuffer")]
private static int SaveToBuffer( ref sbyte[] buf, ref int buf_size );
如果从 C# 程序崩溃调用此函数,这将不起作用。
我想这与 Cdecl 调用模型有关,应该使用 Marshal.AllocHGlobal(value),
我无法想象应该如何正确完成。
我也试过这个:
[DllImport("entry.dll",
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "SaveToBuffer")]
private static int SaveToBuffer( IntPtr buf, ref int buf_size );
然后分配足够的内存
IntPtr data=Marshal.AllocHGlobal(128000);
int bufSize=128000;
var sCode=SaveToBuffer(data,bufSize ); /* value of scode idicate succses*/
通过这种方式调用,我从 SaveToBuffer 中获得了 return 值,指示函数成功但是:bufSize returns 变为 0,我应该如何从 IntPtr 读取数据。
我完全坚持这一点。
这不是调用约定的问题。问题出在缓冲区处理中。
实际上只有一种合理的方式来解释 C++ 参数类型和 return 字节数组的明显意图。也就是说,缓冲区由被调用者分配和填充,其地址 returned in buf
。缓冲区长度在 buf_size
中 returned。
使用这些语义,函数参数无法自动编组,您必须手动进行:
[DllImport("entry.dll", CallingConvention = CallingConvention.Cdecl)]
private static int SaveToBuffer(out IntPtr buf, out int buf_size);
这样调用
IntPtr buf;
int buf_size;
int retval SaveToBuffer(out buf, out buf_size);
// check retval
然后像这样复制到字节数组:
byte[] buffer = new byte[buf_size];
Marshal.Copy(buf, buffer, 0, buf_size);
DLL 还需要导出一个函数来释放非托管缓冲区。
总结: 我正在尝试使用带有 cdecl 调用约定 的 C++ dll 所有 运行 都很好,除非我得到这个方法签名:
int SaveToBuffer( char **buf, int *buf_size );
根据我的阅读,我应该这样使用它:
[DllImport("entry.dll",
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "SaveToBuffer")]
private static int SaveToBuffer( ref sbyte[] buf, ref int buf_size );
如果从 C# 程序崩溃调用此函数,这将不起作用。 我想这与 Cdecl 调用模型有关,应该使用 Marshal.AllocHGlobal(value), 我无法想象应该如何正确完成。
我也试过这个:
[DllImport("entry.dll",
CallingConvention = CallingConvention.Cdecl,
EntryPoint = "SaveToBuffer")]
private static int SaveToBuffer( IntPtr buf, ref int buf_size );
然后分配足够的内存
IntPtr data=Marshal.AllocHGlobal(128000);
int bufSize=128000;
var sCode=SaveToBuffer(data,bufSize ); /* value of scode idicate succses*/
通过这种方式调用,我从 SaveToBuffer 中获得了 return 值,指示函数成功但是:bufSize returns 变为 0,我应该如何从 IntPtr 读取数据。
我完全坚持这一点。
这不是调用约定的问题。问题出在缓冲区处理中。
实际上只有一种合理的方式来解释 C++ 参数类型和 return 字节数组的明显意图。也就是说,缓冲区由被调用者分配和填充,其地址 returned in buf
。缓冲区长度在 buf_size
中 returned。
使用这些语义,函数参数无法自动编组,您必须手动进行:
[DllImport("entry.dll", CallingConvention = CallingConvention.Cdecl)]
private static int SaveToBuffer(out IntPtr buf, out int buf_size);
这样调用
IntPtr buf;
int buf_size;
int retval SaveToBuffer(out buf, out buf_size);
// check retval
然后像这样复制到字节数组:
byte[] buffer = new byte[buf_size];
Marshal.Copy(buf, buffer, 0, buf_size);
DLL 还需要导出一个函数来释放非托管缓冲区。