Home Ask Login Register

Developers Planet

Your answer is one click away!

user595985 February 2016

Python lists and ctypes

Hi I am trying to call a c++ function that has the following signature

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

The idea being from python I can have a list of mountains and their heights, and I can call the c++ function to set their heights. The C++ Function takes 2 arrays. An array with the mountain names and another array with the mountain heights.

So in python I have 2 lists

  • mountains=[kilimanjaro,mount_saina,mount_elgon]
  • mnt_heights=[100.1,200,3331.56]
  • element_count=len(mountains)

I use ctypes and call the c-function as 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)

But it doesn't seem to work, I am not 100% sure if I am creating the array correctly as in both the size and making sure that the mountain strings are properly assigned to the array, similarly for the heights. Am I doing something wrong, or should I look elsewhere for the source of my issue?


I think one of the issues stems from


now the list of mountains is an array of strings, or in python a list of strings, how do I set the argtypes as a list of strings or at least an array of strings.

am I correct in assuming that ctypes.c_char_p which i use in argtypes does NOT allow me to pass into the function an array of strings?. What should i have in argtypes to


Neitsa February 2016

Here's a simple test in C (add 100.0 to 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;

    for (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),

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,
    print("result: {}".format(result))
    if result == 1:
        # change passed list with new results
        del mountain_heights[:]

    return result

def main():
    mountains = ["foo", "bar", "baz"]
    mountain_heights = [100.0, 200.0, 300.0]

    print("Before: {}".format(mountain_heights))

Post Status

Asked in February 2016
Viewed 2,069 times
Voted 8
Answered 1 times


Leave an answer

Quote of the day: live life