我可以跨 DLL 边界传递 FILE 对象吗?

Can I pass FILE object across DLLs boundaries?

我有一个 C++ 框架,其中一些计算委托给(有时是自动生成的)C 函数或具有外部 "C" 链接的 C++ 函数。这些是低级例程,必须以非常快的速度和最小的开销进行评估,它们通常驻留在单独的共享 objects/DLLs 中。他们目前的签名是这样的:

int my_generated_function(const double* input, double* output, double* work);

将驻留在使用 POSIX 上的 dlopen 或 Windows 上的 LoadLibrary 加载的共享库中。使用POSIX上的dlsym(handle, "my_generated_function")或Windows上的GetProcAddress(handle, TEXT("my_generated_function"))提取相应的函数指针。

使用 FILE 对象指针扩充签名是否安全且可移植?

int my_generated_function(const double* input, double* output, double* work,
                          FILE* logfile);

请注意,包含 my_generated_function 的共享对象可能是使用与加载共享对象的代码不同(但二进制兼容)的编译器编译的。

您可以将 FILE* 视为不透明句柄。问题是这个句柄下的实际对象,换句话说,FILE 结构的定义及其实现细节,是 compiler/CRT 具体的。

因此,据我所知,不能保证 FILE 实现例如Visual Studio2008或2010与VS2015或2017中的相同。换句话说,即使结构(FILE)的名称相同,实施细节很可能会从 CRT 的一个版本更改为另一个版本。

所以,我建议 不要 在 DLL 边界有一个 FILE*,除非你想限制你的客户使用 版本的 VC++ compiler/CRT.

另一方面,如果您在 DLL 接口边界需要一个跨 compiler/CRT 兼容句柄,我建议使用 Win32 HANDLE 类型(从 API 返回的类型)像 CreateFile)。这是在 OS 级别定义的,因此它独立于特定的 VC++ compiler/CRT.

如果您想从 FILE* 获取 Win32 HANDLE,您可以使用 _get_osfhandle_fileno,如 this SO answer 中所述。