如何使用python中的Char**参数和int*参数调用C方法?

2024-09-27 00:13:28 发布

您现在位置:Python中文网/ 问答频道 /正文

这是module.py script,它加载包含io.cio.h文件的erf_utils_io_D.dll 我成功地加载了库并传递了ctype参数,如下所示

c_int, c_float, POINTER(c_int), POINTER(c_Float)

模块.py

//python code module.py
    import sys
    from ctypes import *
    #load the required library and make sure the folder where    erf_utils_io_D.dll is present

dll = CDLL('D:\\erf_utils_python\\erf_utils_io.dll')
getContourResults = dll.getContourResults

class Utility(object):
    def __init__(self):
        print('i am inside init')
        self.stagename = "post"
        self.stateids = (c_int * 1) (2934)
        self.stateidcount = 1
        self.entityidcount = 1
        self.entityid = (c_int * 1) (1)
        self.entitytype = "FPM"
        self.variablecount = 1
        self.ores = [1.0]
        self.filename ='allinone_RESULT.erfh5'
        #This is how char** is treted in python for variablegroup
        self.variablegroup = ["FPM_Mach_Number"]
        self.string_length = len(self.variablegroup)
        self.select_type = (c_wchar_p * self.string_length)
        self.select = self.select_type()
        for key, item in enumerate(self.variablegroup):
                 self.select[key] = item


        #This is how char** is treated infor variable
        self.variable = ["FPM_Mach_Number"]
        self.var_len = len(self.variable)
        self.var_type = (c_wchar_p * self.var_len)
        self.variable_list = self.var_type()
        for key, item in enumerate(self.variable):
              self.variable_list[key] = item


    def run(self):
        getContourResults.argtypes = (POINTER(c_char_p), POINTER(c_char_p), c_int, POINTER(c_int),
                              c_int, POINTER(c_int), POINTER(c_char), c_int, self.select_type ,
                              self.var_type, POINTER(c_float))

        getContourResults.restype = (c_int)


        err = getContourResults(self.filename, self.stagename, self.stateidcount,
        self.stateids, self.entityidcount,self.entityid, self.entitytype, self.variablecount, self.select, self.variable_list, self.ores)


reader = Utility()
reader.run()

code.cpp看起来像这样

extern "C"
{
#endif
    __declspec(dllexport) int getContourResults(char* iFilename, char* iStagename, int iStateidCnt, int* Stateids,
        int iEntityIdCount, int* iEntityids, char* iEntityType,
        int iVariablecnt, char** iVariablegroup, char** ivariable,
        float* oResults);
}

请告诉我如何将参数从python脚本传递到io.c中的方法


Tags: ioselfisvartypeutilsvariableselect
1条回答
网友
1楼 · 发布于 2024-09-27 00:13:28

没有迹象表明该功能的实现,所以我做了一些假设。通过这个例子,您应该能够适应您的实际用例。主要修复方法是.argtypes更正和使用c_char_p代替c_wchar_p以及一个简单的帮助函数,用于将列表转换为ctypes数组

以下是关于类型的一些说明:

  • c_char_p==char*在C中。传递一个字节字符串,例如b'string'
  • c_wchar_p==wchar_t*在C中。传递一个Unicode字符串,例如'string'
  • POINTER(c_char_p)==char**在C中
  • POINTER(c_float)==float*在C中。创建存储(c_float())并传递byref。以带有.value成员的Python整数形式访问返回的浮点

测试.cpp

#include <stdio.h>

extern "C" __declspec(dllexport) int getContourResults(char* iFilename, char* iStagename, int iStateidCnt, int* Stateids,
    int iEntityIdCount, int* iEntityids, char* iEntityType,
    int iVariablecnt, char** iVariablegroup, char** ivariable,
    float* oResults)
{
    printf("iFilename = %s\n"
           "iStagename = %s\n"
           ,iFilename,iStagename);
    for(int i = 0; i < iStateidCnt; ++i)
        printf("Stateids[%d] = %d\n",i,Stateids[i]);
    for(int i = 0; i < iEntityIdCount; ++i)
        printf("iEntityids[%d] = %d\n",i,iEntityids[i]);
    printf("iEntityType = %s\n",iEntityType);
    for(int i = 0; i < iVariablecnt; ++i) {
        printf("iVariablegroup[%d] = %s\n",i,iVariablegroup[i]);
        printf("ivariable[%d] = %s\n",i,ivariable[i]);
    }
    *oResults = 1.2f;
    return 5;
}

test.py

from ctypes import *

dll = CDLL('./test')
dll.getContourResults = dll.getContourResults
dll.getContourResults.argtypes = (c_char_p,c_char_p,c_int,POINTER(c_int),c_int,POINTER(c_int),c_char_p,
                              c_int,POINTER(c_char_p),POINTER(c_char_p),POINTER(c_float))
dll.getContourResults.restype = c_int

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

def getContourResults(filename,stagename,sids,eids,entitytype,groups,variables):
    stateidcount,stateids = make_array(c_int,sids)
    entityidcount,entityid = make_array(c_int,eids)
    groups = [b'group1',b'group2']
    variables = [b'var1',b'var2']
    if len(groups) != len(variables):
        raise ValueError('assuming groups and variables same length')
    _,variablegroup = make_array(c_char_p,groups)
    variablecount,variable = make_array(c_char_p,variables)
    ores = c_float()
    err = dll.getContourResults(filename,stagename,stateidcount,stateids,entityidcount,entityid,
                                entitytype,variablecount,variablegroup,variable,byref(ores))
    return err,ores.value

sids = [1,2,3]
eids = [4,5,6]
groups = [b'group1',b'group2']
variables = [b'var1',b'var2']
err,ores = getContourResults(b'filename',b'stagename',sids,eids,b'entitytype',groups,variables)
print(f'err = {err}')
print(f'ores = {ores:.2f}')

输出:

iFilename = filename
iStagename = stagename
Stateids[0] = 1
Stateids[1] = 2
Stateids[2] = 3
iEntityids[0] = 4
iEntityids[1] = 5
iEntityids[2] = 6
iEntityType = entitytype
iVariablegroup[0] = group1
ivariable[0] = var1
iVariablegroup[1] = group2
ivariable[1] = var2
err = 5
ores = 1.20

相关问题 更多 >

    热门问题