c++ - Python lists and ctypes -
hi trying call c++ function has following signature
change_mountain_heights(mnt *mountains[],float32 heights[],int8 num_elements)
the idea being python can have list of mountains , heights, , can call c++ function set heights. c++ function takes 2 arrays. array mountain names , array mountain heights.
so in python have 2 lists
- mountains=[kilimanjaro,mount_saina,mount_elgon]
- mnt_heights=[100.1,200,3331.56]
- element_count=len(mountains)
i use ctypes , call c-function follows,
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)
but doesn't seem work, not 100% sure if creating array correctly in both size and making sure mountain strings assigned array, heights. doing wrong, or should elsewhere source of issue?
update
i think 1 of issues stems from
change_mountain_heights.argtypes=(ctypes.c_char_p,ctypes.c_float,ctypes.c_int8)
now list of mountains array of strings, or in python list of strings, how set argtypes list of strings or @ least array of strings.
am correct in assuming ctypes.c_char_p use in argtypes not allow me pass function array of strings?. should have in argtypes indicate i'll passing in
- an array containing strings
- an array containing float
i'm using python 2.7.10 on windows regards
here's simple test in c (add 100.0 each height) :
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; (int8_t index = 0; index < num_elements; ++index) { char* mountain = mountains[index]; printf("mountain: %s ; height: %f\n", mountain, heights[index]); // add 100.0 heights[index] += 100.0f; } return 1; }
the python code:
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 strings string_pointers = (ctypes.c_char_p * len(mountains))(*mountains) # floats floats = (ctypes.c_float * len(mountain_heights))(*mountain_heights) # pointer 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 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()
output:
before: [100.0, 200.0, 300.0] result: 1 after: [200.0, 300.0, 400.0]
Comments
Post a Comment