【发布时间】:2014-09-30 06:18:37
【问题描述】:
我正在将大量代码从非托管 C++ 程序集重构为 C# 程序集。目前在两者之间有一个混合模式程序集,当然,混合了托管和非托管代码。我试图在依赖 FILE*s(如 stdio.h 中定义的)的非托管 C++ 中调用一个函数。此函数与一个更大的进程相关联,该进程尚不能重构为 C# 代码,但现在需要从托管代码中调用。
我已经搜索过,但找不到关于 System::IO::FileStream 类使用哪种底层系统指针的明确答案。这只是应用在 FILE* 之上吗?还是有其他方法可以将 FileStream^ 转换为 FILE*?我找到了 FileStream::SafeFileHandle,我可以在其上调用 DangerousGetHandle().ToPointer() 来获得原生 void*,但我只是想确定如果我将它转换为 FILE*,我做对了东西……?
void Write(FILE *out)
{
Data->Write(out); // huge bulk of code, writing the data
}
virtual void __clrcall Write(System::IO::FileStream ^out)
{
// is this right??
FILE *pout = (FILE*)out->SafeFileHandle->DangerousGetHandle().ToPointer();
Write(pout);
}
【问题讨论】:
-
看起来是您的最佳选择。不过,似乎无法保证“OS 文件句柄”实际上是 FILE*。但如果是这样,它似乎不太可能改变。您可能必须通过输出流上的 GC.KeepAlive 来防止在本机代码中释放句柄。
-
这真的有什么不同吗?如果数据很大,我预计开销会很小......
-
不,FILE 是严格的 C 运行时抽象,与 Windows 句柄没有任何关系。您可以使用 _fdopen() 破解 32 位代码。
-
@MatsPetersson 问题不在于代码的速度,而在于代码的数量。可能有超过一千行(仅用于编写此特定数据文件)的 C++ 代码需要重构为 C#(从混合模式程序集转变为纯 C# 程序集)。编写文件太大而无法重构,但我正在重构类的其他部分,这意味着我需要能够从托管代码中调用本机的、非托管的 Write 方法。