Awesome, thanks! On Thu, May 11, 2023 at 1:47 PM Eryk Sun <eryk...@gmail.com> wrote:
> On 5/11/23, Jason Qian via Python-list <python-list@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 > -- https://mail.python.org/mailman/listinfo/python-list