我有一个C语言编写的库函数,通过将输出写入FILE *
来生成文本。我想用Python(2.7.x)将其包装起来,使其创建一个临时文件或管道,将其传递给该函数,从文件中读取结果,并将其作为Python字符串返回。
这里是一个简化的示例,以说明我的目的:
/* Library function */
void write_numbers(FILE * f, int arg1, int arg2)
{
fprintf(f, "%d %d\n", arg1, arg2);
}
Python封装器:
from ctypes import *
mylib = CDLL('mylib.so')
def write_numbers( a, b ):
rd, wr = os.pipe()
write_fp = MAGIC_HERE(wr)
mylib.write_numbers(write_fp, a, b)
os.close(wr)
read_file = os.fdopen(rd)
res = read_file.read()
read_file.close()
return res
#Should result in '1 2\n' being printed.
print write_numbers(1,2)
我想知道使用MAGIC_HERE()
的最佳方法是什么。
我倾向于只使用ctypes
并创建一个libc.fdopen()
包装器,返回Python c_void_t,然后将其传递到库函数中。理论上似乎应该是安全的,只是想知道是否存在这种方法的问题或解决此问题的现有Python技术。
此外,这将进入一个长时间运行的进程(假设是“永远”),因此任何泄漏的文件描述符都将成为问题。
os.popen()
是不正确的。它至少需要一个参数,即要调用和获取管道的命令行。此外,根据文档的说法,它已经被subprocess
取代并弃用。 - ivan_pozdeevlibc.fdopen
并传递生成的FILE
指针不会有任何问题。但是,我建议不要使用c_void_p
,而是创建一个不透明的class FILE(Structure): pass
,并设置libc.fdopen.restype = POINTER(FILE)
。这样就不会将其转换为整数结果了。另一方面,c_void_p
作为restype
会被转换为整数,所以您必须确保将mylib.write_numbers.argtypes
也设置好,以防止截断64位指针值。 - Eryk Sunfmemopen
?如果单个write_numbers
调用写入的数据量受到合理小的固定常数的限制,那么它可能是使用管道的良好替代方案。 - 5gon12ederFILE *
。但是,你可以简单地读取你传递给fmemopen
的char[]
数组。 - 5gon12ederfmemopen
允许将模式设置为“r +”或“w +”,这将允许读/写操作。 - Brian McFarland