【问题标题】:How to pass a Pointer of String-Array in a function using Ctypes?如何使用 Ctypes 在函数中传递字符串数组的指针?
【发布时间】:2020-08-09 16:14:56
【问题描述】:

我有这个签名的 C 函数:

void updateCaseFile( char scalarFields[][100], uint nscalars, char vectorFields[][100], uint nvectors, uint* timeList, uint ntimes );

在我的特殊情况下,在 C 中,我通过了:

char scfields[2][100] = {"rho", "T"};

char vfields[1][100] = {"U"};

updateCaseFile(scfields, 2, vfields, 1, timeList, nwrite);

在 Linux 系统中,我想使用 ctypes 从 Python 传递 scfields 和 vfields,所以我使用 ctypes.c_char_p 如下:

import ctypes

libbio = ctypes.CDLL('/home/lib/libio.so')

updateCaseFile = libbio.updateCaseFile

scfields = ["rho" , "T" ]

scfields_array = (ctypes.c_char_p * (len(scfields)+1))()

vfields = ["U"]

vfields_array = (ctypes.c_char_p * (len(vfields)+1))()

updateCaseFile(scfields, 2, vfields, 1, timeList, nwrite)

但我收到此错误:

ArgumentError: argument 1: : 不知道如何转换参数 1

使用 numpy 更改代码

import numpy as np

scfields = np.chararray((1, 2))

scfields = ('rho' , 'T' )

vfields = np.chararray((1, 1))

vfields = ('U')

scfields_p = scfields.ctypes.data_as(c_wchar_p)

vfields_p = vfields.ctypes.data_as(c_wchar_p)

updateCaseFile(scfields, 2, vfields, 1, timeList, nwrite)

我再次收到此错误:

ArgumentError: argument 1: : 不知道如何转换参数 1

我知道在第二种情况下哪个 scfields 在元组中转换,但我找不到问题所在。 如何解决这个问题?

谢谢

【问题讨论】:

    标签: arrays pointers ctypes google-colaboratory


    【解决方案1】:

    您正在创建 char* 数组,而不是二维数组。这是一种初始化正确数组的方法。另请注意定义.argtypes.restype 有助于为您检查ctypes 错误:

    from ctypes import *
    
    dll = CDLL('./test')
    dll.updateCaseFile.argtypes = POINTER(c_char * 100),c_uint,POINTER(c_char * 100),c_uint,POINTER(c_uint),c_uint
    dll.updateCaseFile.restype = None
    
    A = c_char * 100  # make a name for the char[100] type.
    
    # This is *not* fast.  Use a numpy array if you need speed
    def make(*args):
        a = (A * len(args))()          # create a[n][100] array
        for i,arg in enumerate(args):  # initialize each element
            a[i].value = arg.encode()  # encode for byte strings.  Alternatively, pass bytes strings.
        return a
    
    scfields = make('Rho','T')
    vfields = make('U')
    timeList = (c_uint * 2)(1,2)
    dll.updateCaseFile(scfields,2,vfields,1,timeList,2)
    

    使用这个演示 C DLL:

    #include <stdio.h>
    
    typedef unsigned int uint;
    
    __declspec(dllexport) void updateCaseFile( char scalarFields[][100], uint nscalars, char vectorFields[][100], uint nvectors, uint* timeList, uint ntimes )
    {
        for(uint i = 0; i < nscalars; ++i)
            printf("%u: %s\n",i,scalarFields[i]);
        for(uint i = 0; i < nvectors; ++i)
            printf("%u: %s\n",i,vectorFields[i]);
        for(uint i = 0; i < ntimes; ++i)
            printf("%u: %u\n",i,timeList[i]);
    }
    

    输出是:

    0: Rho
    1: T
    0: U
    0: 1
    1: 2
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-21
      • 1970-01-01
      • 2015-06-03
      • 2019-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多