2016-10-29 90 views
1

此時我已經在網上搜索了幾個小時。有誰知道如何解析從python函數返回的一個namedtuple到一個結構或只是分離變量。我遇到麻煩的部分是從返回的指針中獲取數據。我使用PyObject_CallFunction()調用調用嵌入在C++中的python函數,並且我不知道如何將PyObject *返回到返回的數據中。蟒蛇命名爲C++的結構

我使用Python 2.7作爲參考。

編輯:我結束了所有的功能,我正試圖做的Python和C + +到現在只是Python。我將在不久的將來更新關於試圖在這個問題的評論中提出的策略。

+0

您可能無法轉換namedtuple,因爲它不是內建的。先嚐試將namedtuple轉換爲tuple(從python級別),然後在你的C++擴展中使用'PyArg_ParseTuple'。 – thorhunter

+0

@thorhunter我會給你一個鏡頭。在閱讀PyArg_ParseTuple的文檔時,我對於如何訪問每個部分有點困惑。我是否必須確切知道Python用於存儲值的字節數? – Wired365

+0

不,你唯一需要知道的是你傳遞的元組的結構,例如。 (int,int,string)。然後,你可以使用'PyArg_ParseTuple(args,「iis」,&int1,&int2,&str);'爲'int int1; int int2; char * str'變量來將它們綁定到C類型上,這當然是一個基本的例子,你可以使用'PyArg_ParseTuple'和其他Python API元素來做更多的事情,你可以用Python API以某種方式從PyObject中提取任何你需要的信息(包括字符串長度),我發現這個引用非常簡單:https: //docs.python.org/2.0/ext/parseTuple.html – thorhunter

回答

1

我打電話嵌入C++使用 PyObject_CallFunction()調用Python函數,我不知道該怎麼辦,一旦我有 的的PyObject *返回的數據。

A namedtuple是一個元組子類,它另外將元組作爲命名屬性公開。這意味着您可以選擇是否以obj[position]obj.attribute訪問其數據。後者通常更具可讀性,但前者與tuple解包相結合。在Python/C中,將它作爲元組訪問可能更容易,因爲您可以使用便利函數PyArg_ParseTuple,如註釋中所示。

要提取對象的任意屬性(不一定是namedtuple),可以調用PyObject_GetAttrString。鑑於描述,比方說一個對象,一個點,提取這樣的屬性作爲x可能是這樣的:

PyObject *point = ...; // assume we get a new reference to point 
if (!point) 
    return NULL; 
PyObject *x = PyObject_GetAttrString(point, "x"); 
if (!x) { 
    // obj.x raised, possibly because point is of a different type 
    Py_DECREF(point); 
    return NULL; 
} 
double x_val = PyFloat_AsDouble(x); 
Py_DECREF(x);  // x not used below this line 
if (x_val == --1 && PyErr_Occurred()) { 
    // obj.x is not float or float-like 
    Py_DECREF(point); 
    return NULL; 
} 
Py_DECREF(point); // point not used below this line 

的錯誤檢查和引用計數是很乏味,但它可以用後衛類或者基本消除,更好然而,使用其他人編寫的類,如Boost.Python。

+0

感謝您的替代方法。爲什麼您在'x_val && PyErr_Ocurred()'上執行相同的檢查兩次,看起來像是if語句中的相同內容? – Wired365

+0

@ Wired365只是一個複製粘貼錯誤,對不起,我最初編寫的代碼也是爲了獲取'y',但是通過錯誤檢查和referencex計數,結果太長了。我編輯了答案以刪除額外的副本,並將'throw ...'更改爲'return NULL',因爲那是什麼你通常希望在Python/C中完成。 (如果你打算忽略這個錯誤並繼續,記得調用'PyErr_Clear',並可能調用'PyErr_ExceptionMatches'來確保你只忽略了你想忽略的異常,而不是每個異常。 – user4815162342

+0

ahhh好吧這就是我認爲它可能是,但我只是想確保我完全理解你。謝謝澄清! – Wired365

0

namedtuple純粹是用Python實現的。你可以在collections.py中看到它的完整源代碼。這很短。要記住的是namedtuple本身是一個函數,它在調用它的框架中創建一個類,然後返回這個類(不是這個類的一個實例)。這是返回的類,然後用於創建實例。所以如果你想傳遞個體實例,你得到的對象不是你想要傳入C++的東西。

C++在編譯時創建了struct定義。 namedtuple在運行時創建namedtuple類。如果你想將它們綁定到C++結構體上,可以使用PyObject在C++中創建新鑄造的類實例,並在編譯時將它們分配給struct元素。或者在Python中創建新的類實例並將它們傳遞給C++。

或者您可以使用_asdict方法(由所有構建類的namedtuple factory方法提供)並將其傳遞給C++,然後將運行時定義的數據綁定到編譯時定義的數據。

如果你真的想在C++中完成大部分的工作,你也可以使用Struct模塊而不是使用namedtuple。

namedtuple真的是Python中的數據保留在Python中的瑞士軍刀。它提供了位置訪問,命名訪問,並且所有元素也都是「屬性」(因此它們有fget訪問器方法,可用於地圖,過濾器等,而不必編寫自己的lambda表達式)。

這就像DB綁定(當你不知道哪些列在運行時會在那裏)。與OrderedDict相比,它將數據從一種格式轉換爲另一種格式不那麼笨重。當它以這種方式使用時,處理字符串的開銷與db的實際訪問(甚至嵌入)相比沒有任何意義。但是我不會使用namedtuple來計算大數組結構。