FILE* 的二进制兼容性

3
我正在设计一个执行一些数学计算的C库。我需要指定序列化接口来保存和加载一些数据。问题是,从二进制兼容性的角度来看,在公共API中使用FILE*指针是否正确?目标平台如下:
- Linux x86、x86_64,gcc >= 3.4.6 - Windows x86、x86_64,WinXP >= VS 2008sp1
我需要尽可能保持二进制兼容性,因此目前我的变体如下:
void SMModuleSave(SMModule* module, FILE* dest);
SMModule* SMModuleLoad(FILE* src);

我很好奇,是使用FILE*还是更好地切换到wchar*/char*?


我最终决定使用文件描述符,因为能够从Python和Matlab脚本中使用此库非常重要。这两种语言都提供了fd,但没有FILE*。因此,我决定使用它,尽管fileno不在C标准中。 - prokher
又出现了一个问题:据我所知,如果使用静态C运行时(使用/MT、/MTd)构建的dll的API,则同时使用文件描述符和FILE是不正确的。[msdn-link](http://msdn.microsoft.com/en-us/library/ms235460%28v=vs.80%29.aspx)。我很困惑。我真的不想在API中使用文件名,因为这将限制其仅适用于磁盘上的文件。相反,使用fd或FILE可以使任何流可用,但对于静态CRT来说并非如此。我被卡住了。 :( - prokher
4个回答

4
我不同意ThiefMaster的观点:在存在等效的可移植解决方案时,使用本机文件描述符类型(如Linux上的int类型和Windows上的void *类型)没有任何好处。
我可能会选择使用FILE *而不是从库内部按名称打开文件:这可能对库用户更加麻烦,但它也更加灵活,因为大多数libc实现提供了各种文件打开方式(如fopen()、_wfopen()、_fdopen()、fdopen()、fmemopen()等),你不必自己维护单独的宽字符API。

是的,这正是我们的想法,避免维护单独的宽字符版本。谢谢。 - prokher

2
我不会使用任何一种方法,但可以让用户将文件描述符作为整数传递。然后,您可以在代码中使用fdopen()函数来获取FILE*类型的指针。
然而,在Windows中使用这种方法可能并不是最好的解决方案,即使它确实有一些帮助函数可以获得数字文件描述符。
传递一个FILE*类型的指针或一个const char*类型的指针也可以,但如果库负责打开/关闭文件,则我更喜欢传递文件名,因为这样需要编写的代码更少。

文件描述符和FILE*在这种用例中大多是可以互换的,因为您始终可以通过fdopen()fileno()从一个中获取另一个;但是,它们只有一个是C标准库的一部分,我很好奇为什么会选择不太便携的解决方案? - Christoph
选择文件描述符而不是 FILE * 有几个非常好的理由:当您需要能够从 IO 错误中恢复时,当您想要进行非阻塞 IO 或控制程序何时会阻塞时,或者当您需要确保在让另一个进程/程序继承打开文件时不会丢失缓冲区中的任何输入。这些都似乎不适用于此处,因此我会使用 FILE * - R.. GitHub STOP HELPING ICE
实际上,我最终决定使用文件描述符,因为能够从Python和Matlab脚本中使用此库非常重要。这两种语言都提供fd,但不提供FILE*。所以我决定使用它,尽管fileno不在C标准中。 - prokher

1

是的,从稳定的二进制接口角度来看,在这里使用FILE *是正确的。我想也许您将其与使用FILE本身混淆了。请注意,您的标准库中的fopenfgets等函数都使用(作为参数和返回值)FILE *类型作为其公共接口的一部分。


0

FILE * 是标准 ANSI/ISO C89 和 C99(甚至 K&R)类型。它是可移植性的理想选择,我更喜欢它而不是其他任何东西。您可以放心使用它。没有比它更好的了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接