通过ctypes在Windows中将文件描述符传递给C库函数
我正在尝试通过ctypes把一个文件描述符传递给一个C语言函数,在这个函数里会对这个文件描述符进行写操作。在Linux上这个方法可以正常工作,但在Windows上却不行,我不明白为什么(我在Windows开发方面没有经验)。
//C func signature:
void fun(struct bah *opaque, int fd)
从Python代码(具体细节省略):
mylib.fun.argtypes = [POINTER(bah), c_int]
fh = open(filename,'wb')
#doesn't work on windows, works on linux/unix
mylib.fun(some_ctypes_struct, fh.fileno())
#doesn't work on windows
mylib.fun(bah_struct, ctypes.cdll.msvcrt._open(filename,_O_FLAGS_MASK, ACCMASK)
#doesn't work
mylib.fun(bah_struct, os.open(...))
程序在执行write()时崩溃,并出现了一个失败的断言 _osfile(fh) & FOPEN。
使用的编译器是cl.exe: 16.00.40219.01,适用于x86架构,Python版本是2.7.2,msvc v.1500,32位。
我该怎么做呢?不,我不想把open()的操作交给库来处理。我想安全地传递一个已经打开的文件描述符,并且希望这个方法在不同的平台上都能用。
附加信息,以防万一:这个库是tinycdb,我快速将它移植到Windows上,使用了一个简单的cmake配置和一些小的补丁来让getopt和dll导出正常工作。这个库和可执行工具的功能都正常(已经测试过)。tinycdb的Python ctypes封装在Linux上也能正常工作。但在Windows上却让我很困惑。即使我在用自己的(msvcrt)_open库调用打开文件后传递文件描述符,它也不接受这个fd是一个有效的描述符。
当然,如果我在库内部进行open()和close()操作,一切都能正常工作,但我无法改变API。
1 个回答
4
Windows不像Unix那样使用文件描述符,所以我猜测文件描述符是由C语言的运行时环境模拟出来的。如果你使用了两个不同的C语言运行时(比如说,你的EXE和DLL是用不同的编译器编译的,或者是用同一个编译器但设置了不同的选项),那么每个运行时就会有自己的一套“文件描述符模拟”,这样你就不能把一个运行时的描述符传给另一个运行时。