Python lists and ctypes

Python lists and ctypes

本文关键字:ctypes and lists Python      更新时间:2023-10-16

嗨,我正在尝试调用具有以下签名的c ++函数

change_mountain_heights(mnt *mountains[],float32 heights[],int8 num_elements)

这个想法来自python,我可以有一个山脉及其高度的列表,我可以调用c ++函数来设置它们的高度。C++函数需要 2 个数组。一个带有山名的数组和另一个带有山高的数组。

所以在 python 中我有 2 个列表

  • 山=[乞力马扎罗山,mount_saina,mount_elgon]
  • mnt_heights=[100.1,200,3331.56]
  • element_count=透镜(山脉(

我使用 ctype 并调用 c 函数,如下所示,

def change_heights(mountain_list,height_list,element_count):
    mountain_array=(ctypes.c_char_p * len(mountain_list))(*mountain_list)
    height_array=(ctypes.c_float * len(height_list))(*height_list)
    element_count_param=ctypes.c_int8(element_count)
    change_mountain_heights.argtypes=(ctypes.c_char_p,ctypes.c_float,ctypes.c_int8)
    _success=change_mountain_heights(mountain_array,height_array,element_count_param)

但它似乎不起作用,我不是 100% 确定我是否正确创建了数组,就像大小一样,并确保山字符串正确分配给数组,类似于高度。我做错了什么,还是应该在其他地方寻找问题的根源?

更新

我认为其中一个问题源于

    change_mountain_heights.argtypes=(ctypes.c_char_p,ctypes.c_float,ctypes.c_int8)

现在山脉列表是一个字符串数组,或者在 Python 中是一个字符串列表,如何将 argtypes 设置为字符串列表或至少是一个字符串数组。

假设我在 argtypes 中使用的ctypes.c_char_p不允许我将字符串数组传递到函数中是否正确?我应该在 argtype 中有什么来指示我将传入

  1. 包含字符串的数组
  2. 包含浮点数的数组

我在Windows上使用python 2.7.10问候

这是 C 语言中的简单测试(每个高度加 100.0(:

TMPDLL_API /* export */
int WINAPIV change_mountain_heights(char* mountains[], float heights[], int8_t num_elements)
{
    if (num_elements <= 0)
        return 0;
    if (!(mountains && heights))
        return 0;
    for (int8_t index = 0; index < num_elements; ++index) {
        char* mountain = mountains[index];
        printf("mountain: %s ; height: %fn", mountain, heights[index]);
        // add 100.0
        heights[index] += 100.0f;
    }
    return 1;
}

蟒蛇代码:

import ctypes
import os
current_dir = os.path.dirname(os.path.realpath(__file__))
dll_path = os.path.join(current_dir, "tmpDll.dll")
_tmp_dll = ctypes.CDLL(dll_path)
# int change_mountain_heights(char* mountains[], float heights[], int8_t num_elements)
_tmp_dll.change_mountain_heights.restype = ctypes.c_int  # default, not required
_tmp_dll.change_mountain_heights.argtypes = (
    ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_float),
    ctypes.c_int8)

def change_mountain_heights(mountains, mountain_heights):
    if len(mountains) != len(mountain_heights):
        raise ValueError()
    # pointer to strings
    string_pointers = (ctypes.c_char_p * len(mountains))(*mountains)
    # floats
    floats = (ctypes.c_float * len(mountain_heights))(*mountain_heights)
    # pointer to floats
    pfloat = ctypes.cast(floats, ctypes.POINTER(ctypes.c_float))
    # call C function
    result = _tmp_dll.change_mountain_heights(string_pointers, pfloat,
                                              len(mountain_heights))
    print("result: {}".format(result))
    if result == 1:
        # change passed list with new results
        del mountain_heights[:]
        mountain_heights.extend(list(floats))
    return result

def main():
    mountains = ["foo", "bar", "baz"]
    mountain_heights = [100.0, 200.0, 300.0]
    print("Before: {}".format(mountain_heights))
    change_mountain_heights(mountains, mountain_heights)
    print("After: {}".format(mountain_heights))
if __name__ == "__main__":
    main()

输出:

Before: [100.0, 200.0, 300.0]
result: 1
After: [200.0, 300.0, 400.0]