2013-02-13 83 views
1

的使用StringIO的我有以下的方法,我换使用痛饮访问它在Python:的Python和痛饮:到位FILE *

void some_class::some_method(FILE *fp, int *pT, int **pO) { 
    fscanf(fp, "lalala", pT); 

怎么可能传递一个StringIO的第一个论点?我应该使用哪种类型图?

+0

完整性检查:你只是从'FILE *'中读取而不写入它? – Flexo 2013-02-18 12:53:39

+0

是的,只读 – warden 2013-02-20 08:36:38

回答

0

简单的解决方案是构建一个使用fmemopen为您自动创建FILE*的类型映射。我创建了一个例子:

%module test 
%include <typemaps.i> 

%typemap(in) FILE *sb (PyObject *str=NULL) { 
    str = PyObject_CallMethod($input, "getvalue", NULL); 
    char *buf = NULL; 
    int len = 0; 
    PyString_AsStringAndSize(str, &buf, &len); 
    $1 = fmemopen(buf, len, "r"); 
} 

%typemap(freearg) FILE *sb { 
    if ($1) fclose($1); 
    Py_XDECREF(str$argnum); 
} 

%apply int *OUTPUT { int * i }; 

%inline %{ 
    void foo(FILE *sb, int *i) { 
    fscanf(sb, "%d", i); 
    } 
%} 

有两个部分这一点,首先有一些Python的C API调用的StringIOgetvalue,以获得访问所保存的数据。这个缓冲区至少需要和FILE*一样长,所以我们必须引入一个额外的变量并在完成后清理它。

我也使用%apply自动将int *i作为输出而不是输入。这可能足以做你想做的事情。

这足以让我运行下面的测试程序:

import StringIO 
import test 

buf=StringIO.StringIO("666") 
print test.foo(buf) 

如果你想使界面更加通用的,我建议将调用PyFile_AsFile处理的Python文件对象真的是文件,而不仅仅是StringIO对象。您可以检查返回值,尝试将您提供的参数用作许多不同可行类型的输入。

这是非常令人费解的。更好的解决方案是使用cStringIO,这会给你一个直接的C API,完全避免了对getvalue的调用。如果您使用的是glibc,则可以使用fopencookieFILE*直接挂接到cStringIO对象以进行零拷贝。

+0

哇,谢谢你的广泛答案! – warden 2013-02-20 08:37:04