我有以下本机 C++ 函数:
// Decode binary format from file 'filename' into stream 'output'
bool read_private_format(const char * filename, std::ostringstream & output);
阅读上一篇关于 StringBuilder 和 delegate 的文章,我创建了一个中间 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*
是不同的)。
我的问题是:
我事先不知道绳子有多长。从技术上讲,我可能会高估 StringBuilder 的容量,以便我可以在文件中重复使用,但感觉好像可以有更好的方法将不断增长的流传递到 c 层。
尝试优化发布的代码是没有意义的,因为根据定义,pinvoke 层缺少最重要的一点:
❌ 避免 StringBuilder 参数。 StringBuilder 始终封送 创建本机缓冲区副本。因此,它可能非常 效率低下。