亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何從內存分配發生在C層的Python腳本將float*數組傳遞給C方法

如何從內存分配發生在C層的Python腳本將float*數組傳遞給C方法

喵喔喔 2023-10-26 15:13:07
我試圖從Python腳本調用C方法,C方法調用反過來C++方法。我使用 malloc() 在 getResults() 方法內分配數組?,F在的問題是如何將參數傳遞給 python 腳本中的 float* oresults,其內存分配發生在 C 層內。這是io.cint 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;}TypeError: byref() 參數必須是 ctypes 實例,而不是 '_ctypes.PyCPointerType' 這是我運行腳本時收到的錯誤。我對如何在腳本中發送 float *oresults 的參數有點困惑。
查看完整描述

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)()創建這樣一個指針的實例(最初為空)。

查看完整回答
反對 回復 2023-10-26
?
慕婉清6462132

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]


查看完整回答
反對 回復 2023-10-26
  • 2 回答
  • 0 關注
  • 165 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號