2013-02-22 60 views
3

我正在爲使用C++編寫的小型音頻庫創建Python擴展的過程。打開音頻流時,回調函數作爲參數傳遞(當然還有其他參數)。一個簡單的用例:從C線程調用帶有可變C數組的Python函數

AudioThingy *a = new AudioThingy(); 
a->openStream(..., callbackFunction); 
a->startStream(); 

我的Python擴展將它封裝在Python類中。

thingy = AudioThingy() 
thingy.openStream(..., pythonCallbackFunction) 
thingy.startStream() 

現在,該擴展有一個回調函數作爲C函數傳遞給C++庫。對於每個流勾號,回調會根據流格式參數接收一些關於流的信息以及一個指向音頻緩衝區的void指針,以便回調將其轉換爲正確的數據類型。我的意圖當然是在C中實現的這個回調函數用某種數組作爲參數調用用戶指定的Python函數,然後用來自例如用Python打開的wav文件填充音頻數據。

這就是我想做的事,在代碼:

static int __audiothingy_callback(void *buffer, ...) { 
    PyGILState_STATE state = PyGILState_Ensure(); 
    /* 
     cast the void pointer to the correct data type (short, int, long, etc.) 
     wrap it for Python somehow 
    */ 
    PyEval_CallObject(the_python_function, arglist); 
    PyGILState_Release(state); 
    //proceed to fill the buffer with stuff passed back from python 
    for (...) 
    *casted_buffer++ = ???? 
    Py_DECREF(arglist); 
    return 0; 
} 

TL; DR:我如何通過從C正確類型的可變數組,在一個線程,爲Python功能,可以然後用來填充音頻緩衝區?也許它可以以不同於我上面描述的方式完成?所有的投入是受歡迎的

回答

1

我想你可以做幾件事情。如果你使用的是Python 2.7,你可以使用新的緩衝區協議創建memoryview對象:

然後,你需要從緩衝區創建memoryview對象:

另一個策略是導入陣列模塊,和使用J是創建一個所需類型的數組。可以使用:

然後,構建陣列,根據type needed

PyObject *array = PyObject_CallFunction(array_type, "c", 'd'); 

更容易,你可以只使用一個ByteArray對象:

+0

我接受這個答案,雖然它並沒有完全讓我一路。新問題在這裏:http://stackoverflow.com/questions/15244255/using-py-buffer-and-pymemoryview-frombuffer-with-different-itemsizes – manneorama 2013-03-06 10:06:40