2013-02-13 85 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