2 回答

TA貢獻1803條經驗 獲得超3個贊
在 C++ 代碼中,簽名int getResults(..., float* oResults)
無法將分配的指針傳回調用者。線路
oResults?=?(float*)malloc(results.size()?*?sizeof(float));
在 getResults 中本地設置oResults
指針,而不影響調用者。為了輸出指針,您必須使用return
它或使用指針到指針參數:int getResults(..., float** oResults)
。
在Python代碼中,我不熟悉ctypes,但它看起來float_values = POINTER(c_float)
是一個問題。為浮點指針POINTER(c_float)
創建 Python類型。您想要POINTER(c_float)()
創建這樣一個指針的實例(最初為空)。

TA貢獻1804條經驗 獲得超2個贊
該float* oResults參數是按值傳遞的,因此不可能返回該參數中已分配的指針。相反,使用float** oResults.
另外,float_values = POINTER(c_float)是類型,而不是類型的實例。所以byref(float_values)相當于無效的 C &(float*)。相反,您需要一個指針的實例POINTER(c_float)()(注意括號)并通過引用傳遞它,類似于 C float *p; func(&p)。這會將指針按地址傳遞給 C 函數,然后函數可以將其修改為輸出參數。
這是一個簡化的示例,僅關注int *oRescount和float** oResults參數。還需要一個釋放分配的函數:
測試.cpp
#include <vector>
#define API __declspec(dllexport)
extern "C" {
API int getResults(size_t *oRescount, float** oResults) {
std::vector<float> results {1.25,2.5,3.75,5.0}; // Simulated results
*oRescount = results.size(); // Return size of results
auto tmp = new float[results.size()]; // allocate
for(size_t i = 0; i < results.size(); ++i) // copy vector to allocation
tmp[i] = results[i];
*oResults = tmp; // return allocation
return 0;
}
API void freeResults(float* oResults) {
delete [] oResults;
}
}
test.py
from ctypes import *
dll = CDLL('./test')
dll.getResults.argtypes = POINTER(c_size_t),POINTER(POINTER(c_float))
dll.getResults.restype = c_int
def getresults():
oRescount = c_size_t() # instance to hold the returned size
oResults = POINTER(c_float)() # instance of a float* to hold the returned allocation.
err = dll.getResults(byref(oRescount), byref(oResults))
# oResults is a float* and it is possible to index past the end.
# Make a copy into a Python list slicing to the correct size,
# then free it so there is no memory leak.
results = oResults[:oRescount.value]
dll.freeResults(oResults)
return err,results
err,ores = getresults()
print(err,ores)
輸出:
0 [1.25, 2.5, 3.75, 5.0]
添加回答
舉報