【问题标题】:Pinvoke cdecl convention with char**使用 char 调用 cdecl 约定**
【发布时间】:2015-04-16 05:45:39
【问题描述】:

总结: 我正在尝试使用带有 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 获得返回值,指示函数成功但是:bufSize 返回 0 以及我应该如何从 IntPtr 读取我的数据。

我完全坚持这一点。

【问题讨论】:

    标签: c# c++ char pinvoke


    【解决方案1】:

    这不是调用约定的问题。问题在于缓冲区处理。

    实际上只有一种合理的方式来解释 C++ 参数类型以及返回字节数组的明显意图。即缓冲区由被调用者分配和填充,其地址在buf 中返回。缓冲区长度在buf_size 中返回。

    使用这些语义,函数参数无法自动编组,您必须手动进行:

    [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 还需要导出一个函数来释放非托管缓冲区。

    【讨论】:

      猜你喜欢
      • 2012-03-17
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多