gpt4 book ai didi

python - 如何从在C层进行内存分配的python脚本中将float *数组传递给C方法

转载 作者:行者123 更新时间:2023-12-03 07:02:07 26 4
gpt4 key购买 nike

我正在尝试从Python脚本调用C方法,C方法调用又将C++方法调用。我正在使用malloc()在getResults()方法内部分配数组。现在的问题是如何在python脚本中将参数传递给float * oresults,该脚本的内存分配发生在C层内。
这是io.c

int getResults(char* iFilename, char* iStagename, int iStateidCnt, 
int* Stateids, int iEntityIdCount, int* iEntityids, char* iEntityType,
char* iVariablegroup, char* ivariable, int *oRescount,
float* oResults)
{
int Status, i;
EString etype(iEntityType), stagename(iStagename);
EString vargroup(iVariablegroup);
std::vector<ERF_INT> entity_ids;
std::vector<ERF_INT> stateids;
std::vector<ERF_FLOAT> results;
_CopyIntArrayIntoVector(iStateidCnt, Stateids, stateids);
_CopyIntArrayIntoVector(iEntityIdCount, iEntityids, entity_ids);
CreateIoInstance(iFilename, iStagename);
ioData pIodata = CreateIoDataInstance();
if (iEntityIdCount <= 0)
pIodata.setWholeSection(true);
else
{
pIodata.setWholeSection(false);
pIodata.setEntityList(entity_ids);
}

pIodata.setStateList(stateids);
pIodata.setType(etype);
pIodata.setVariableGroup(iVariablegroup);
pIodata.setVariable(ivariable);
//This is C++ method
Status = pIo->get_results(pIodata, results);
*oRescount = results.size();
//allocation for oresults whose size > 2
oResults = (float*)malloc(results.size() * sizeof(float));
_CopyVectorIntoDoubleArray(results, oResults);
return Status;
}

test.py
from ctypes import *
import os, sys
dll = CDLL('D:\\erf_utils_python\\erf_utils_io.dll')
dll.getresults.argtypes = (c_char_p,c_char_p,c_int,POINTER(c_int),c_int,POINTER(c_int),c_char_p,
c_char_p,c_char_p,POINTER(c_int),POINTER(c_float))
dll.getresults.restype = c_int


def make_array(ctype,arr):
return len(arr),(ctype * len(arr))(*arr)

def getresults(filename,stagename,sids,eids,entitytype,groups,variables):
if(len(sids)>0):
stateidcount,stateids = make_array(c_int,sids)
if(len(eids)>0):
entityidcount,entityid = make_array(c_int,eids)
oresultlen = c_int()
float_values = POINTER(c_float)
err = dll.getresults(filename,stagename,stateidcount,stateids,entityidcount,entityid,
entitytype,groups,variables,byref(oresultlen), byref(float_values))
return err,oresultlen.value, float_values

filename = b'D:\\inputfile.h5'
stagename = b"post"
stateids = [2]
stateidcount = 1
entityidcount = 1
entityid = [1]
entitytype = b"test"
variablecount = 1
variablegroup = b"testdata"
variable = b"next"

err,oreslen,ores = getresults(filename,stagename,stateids,entityid,entitytype,variablegroup,variable)

TypeError: byref() argument must be a ctypes instance, not'_ctypes.PyCPointerType' this is the error I get when I run thescript. I am little confused on how to send argument for float*oresults in script.

最佳答案

float* oResults参数通过值传递,因此不可能在该参数中返回分配的指针。而是使用float** oResults
另外,float_values = POINTER(c_float)是类型,而不是类型的实例。因此byref(float_values)等效于无效的C &(float*)。相反,您需要一个指针POINTER(c_float)()的实例(请注意括号)并通过引用将其传递,类似于C float *p; func(&p)。这会将指针按地址传递给C函数,然后可以将其修改为输出参数。
这是一个简化的示例,仅关注int *oRescountfloat** oResults参数。还需要一个释放分配的函数:
测试文件

#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]

关于python - 如何从在C层进行内存分配的python脚本中将float *数组传递给C方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64312490/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com