Help on ctypes.POINTER for Python array

Eryk Sun eryksun at gmail.com
Thu May 11 13:47:50 EDT 2023


On 5/11/23, Jason Qian via Python-list <python-list at python.org> wrote:
>
> in the Python, I have a array of string
> var_array=["Opt1=DG","Opt1=DG2"]
> I need to call c library and  pass var_array as parameter
> In the   argtypes,  how do I set up ctypes.POINTER(???)  for var_array?
>
> func.argtypes=[ctypes.c_void_p,ctypes.c_int, ctypes.POINTER(????)]
>
> In the c code:
> int  func (void* obj, int index,  char** opt)

The argument type is ctypes.POINTER(ctypes.c_char_p), but that's not
sufficient. It doesn't implement converting a list of str objects into
an array of c_char_p pointers that reference byte strings. You could
write a wrapper function that implements the conversion before calling
func(), or you could set the argument type to a custom subclass of
ctypes.POINTER(ctypes.c_char_p) that implements the conversion via the
from_param() class method.

https://docs.python.org/3/library/ctypes.html#ctypes._CData.from_param

Here's an example of the latter.

C library:

    #include <stdio.h>

    int
    func(void *obj, int index, char **opt)
    {
        int length;
        for (length=0; opt[length]; length++);
        if (index < 0 || index >= length) {
            return -1;
        }
        return printf("%s\n", opt[index]);
    }


Python:

    import os
    import ctypes

    lib = ctypes.CDLL('./lib.so')
    BaseOptions = ctypes.POINTER(ctypes.c_char_p)

    class Options(BaseOptions):
        @classmethod
        def from_param(cls, param):
            if isinstance(param, list):
                new_param = (ctypes.c_char_p * (len(param) + 1))()
                for i, p in enumerate(param):
                    new_param[i] = os.fsencode(p)
                param = new_param
            return BaseOptions.from_param(param)

    lib.func.argtypes = (ctypes.c_void_p, ctypes.c_int, Options)


demo:

    >>> opts = ['Opt1=DG', 'Opt1=DG2']
    >>> lib.func(None, 0, opts)
    Opt1=DG
    8
    >>> lib.func(None, 1, opts)
    Opt1=DG2
    9


More information about the Python-list mailing list