【发布时间】:2022-06-23 00:52:03
【问题描述】:
我想使用与 C 数据类型“const char**”匹配的 ctypes 创建一个 Python 数据类型,它类似于一个指针数组。但是,我无法在 Python 中对此进行编码。 简化的 C 函数头如下所示:
int foo(int numOfProp, const char** propName, const char** propValue);
在 C 中,正确的函数调用如下所示:
const char *PropName[2];
PropName[0] = "Prop_Index_1";
PropName[1] = "Prop_Index_2";
const char *PropValue[2];
PropValue[0] = "10";
PropValue[1] = "20";
stream_id = (*foo)(2, PropName, PropValue);
基本上,该函数采用两个数组(名称和值对)以及两个数组的长度,并返回一个流 ID。加载 DLL 后,我可以看到该函数需要属性数组的此 ctypes 数据类型:
“LP_c_char_p”
但是,我真的很难根据字符串列表创建这种数据类型。
我的第一次尝试(基于How do I create a Python ctypes pointer to an array of pointers)如下所示:
# set some dummy values
dummy_prop_values = [
"10",
"20"
]
# create property dict
properties = {
f"Prop_Index_{i}": dummy_prop_values[i] for i in range(len(dummy_prop_values))
}
def first_try():
# create a dummy ctype string
ctypes_array = ctypes.c_char_p * 2
# create empty c-type arrays for the stream properties
prop_names = ctypes_array()
prop_values = ctypes_array()
# fill the empty arrays with their corresponding values
for i, (prop_name, prop_value) in enumerate(properties.items()):
prop_names[i] = prop_name.encode()
prop_values[i] = prop_value.encode()
# get pointer to properties
ptr_prop_names = ctypes.pointer(prop_names)
ptr_prop_values = ctypes.pointer(prop_values)
return ptr_prop_names, ptr_prop_values
当我将返回的值交给函数 foo 时,它会引发这种错误(这实际上是有道理的,因为我明确地创建了一个长度为 2 的数组......我不知道这对其他人问这个问题):
ctypes.ArgumentError: argument 2: <class 'TypeError'>: expected LP_c_char_p instance instead of LP_c_char_p_Array_2
我的第二次尝试(或多或少基于我自己的想法)如下所示:
def second_try():
# convert properties to lists
prop_names = [x for x in properties.keys()]
prop_values = [x for x in properties.values()]
# concat list elements, zero terminated
# but I guess this is wrong anyway because it leads to an early string-termination (on byte-level)...?
prop_names = ctypes.c_char_p("\0".join(prop_names).encode())
prop_values = ctypes.c_char_p("\0".join(prop_values).encode())
# get pointer to properties
ptr_prop_names = ctypes.pointer(prop_names)
ptr_prop_values = ctypes.pointer(prop_values)
return ptr_prop_names, ptr_prop_values
这实际上并没有抛出错误,而是返回 -1 作为流 ID,这表示“创建流不成功”。我仔细检查了函数调用的所有其他参数,这两个属性是唯一可能以某种方式出错的属性。
无论出于何种原因,我都无法弄清楚我到底在哪里犯了错误,但希望这里有人能指出我正确的方向。
【问题讨论】: