从本机库读取流到 C#

问题描述 投票:0回答:1

我有以下本机 C++ 函数:

// Decode binary format from file 'filename' into stream 'output'
bool read_private_format(const char * filename, std::ostringstream & output);

阅读上一篇关于 StringBuilderdelegate 的文章,我创建了一个中间 C 函数以暴露给 C# 层:

extern "C" {
  typedef char *(*StringBuilderCallback)(int len);
  __attribute__ ((visibility ("default")))
  bool c_read_private_format(const char * filename, StringBuilderCallback ensureCapacity, char *out, int len) {
    std::ostringstream oss;
    if( read_private_format(filename, oss) ) {
      const std::string str = oss.str();
      if( str.size() > len )
        out = ensureCapacity(str.size());
      strcpy(out, str.c_str());
      return true;
    }
    return false;
  }
}

在 C# 端:

private delegate System.Text.StringBuilder StringBuilderEnsureCapacity(int capacity);
[System.Runtime.InteropServices.DllImport(NativeLibraryName, EntryPoint="c_read_private_format")]
private static extern bool c_read_private_format(string filename, System.IntPtr aCallback, System.Text.StringBuilder data, int size);

private static System.Text.StringBuilder callback(int capacity)
{
    buffer.EnsureCapacity( capacity );
    return buffer;
}

public static string readIntoString(string filename) {
  StringBuilderEnsureCapacity del = new StringBuilderEnsureCapacity(callback);
  System.IntPtr ptr = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(del)
  if( c_read_private_format( ptr, buffer, buffer.Capacity ) ) {
    string str = buffer.ToString();
    return str;
  }
  return null;
}

由于某种原因,这没有按预期工作,当打印

char*
返回的
callback
的地址时,它的作用就好像返回的指针是调用
EnsureCapacity
之前的指针(我可以通过执行以下操作来验证)第二次调用,此时C层中的
char*
是不同的)。

我的问题是:

  • 如何在 .NET SDK (5.0.202) 中有效地从 C 检索 UTF-8 字符串?

我事先不知道绳子有多长。从技术上讲,我可能会高估 StringBuilder 的容量,以便我可以在文件中重复使用,但感觉好像可以有更好的方法将不断增长的流传递到 c 层。

c# .net-core stream pinvoke
1个回答
1
投票

尝试优化发布的代码是没有意义的,因为根据定义,pinvoke 层缺少最重要的一点:

❌ 避免 StringBuilder 参数。 StringBuilder 始终封送 创建本机缓冲区副本。因此,它可能非常 效率低下。

© www.soinside.com 2019 - 2024. All rights reserved.