如何使用Ctypes在函数中传递字符串数组的指针?

问题描述 投票:0回答:1

我具有此签名的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:参数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:参数1 ::不知道如何转换参数1

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

谢谢

arrays pointers ctypes google-colaboratory
1个回答
0
投票

您正在创建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
© www.soinside.com 2019 - 2024. All rights reserved.