Re: handling a (python) list to fit in a char** argument
"Mark Tolonen" <[email protected]> Sat, 11 Dec 2010 09:24:50 -0800
| Newsgroups | gmane.comp.python.ctypes |
|---|---|
| Message-ID | <[email protected]> |
"LukenShiro" <[email protected]> wrote in message news:[email protected]... Hello, I'm developing a LGPL-licensed wrapper to XForms-toolkit, using ctypes (a wonderful library, indeed!). A C function to be wrapped has a "char **" argument, so I've ctypes.POINTER(ctypes.c_char_p) as an .argtypes In the wrapping python function I think to use a "list of strings", corresponding to X11-Pixmap (.xpm file) <*> (as you can see it can have a variable number of elements and each element is a string who can have a variable number of chars. I'd use the following function to do a preliminary type check and to operate a data conversion from one type to another: § def convert_to_ptr_string(paramname): § """ Converts paramname (list of str) to a ctypes pointer to c_char_p """ § if isinstance(paramname, list): # list of str § for idx in range(0, len(paramname)): § if not isinstance(paramname[idx], basestring): § # every part must be a str § .... raise a TypeError ..... § myarray = (ctypes.c_char_p * len(paramname))() § for idx in range(0, len(paramname)): § myarray[idx] = ctypes.c_char_p(paramname[idx]) § retv = ctypes.POINTER(myarray) § return retv § else: § .... raise a TypeError ..... But, when called, I get: Traceback (most recent call last): File "./test_flbitmap.py", line 300, in test_fl_set_pixmap_data_ok xfl.fl_set_pixmap_data(self.pxmobj, self.xpmdatalist) File "/usr/lib64/python2.6/site-packages/xformslib/flbitmap.py", line 406, in fl_set_pixmap_data pxpmdatalist = library.convert_to_ptr_string(xpmdatalist) File "/usr/lib64/python2.6/site-packages/xformslib/library.py", line 266, in convert_to_ptr_string retv = cty.POINTER(myarray) TypeError: must be a ctypes type So 'myarray[idx] = cty.c_char_p(paramname[idx])' seems to give the same result as 'myarray[idx] = paramname[idx]' (same error) Am I missing anything obvious? How can I resolve this one? ----------------------- To convert your list of strings array, use: def convert_to_ptr_string(paramname): return (c_char_p * len(paramname))(*paramname) and pass the return value of this function directly to your function that takes POINTER(c_char_p). Below is my test code: ---- x.c (compiled with "cl /W4 /LD x.c") --- #include <stdio.h> __declspec(dllexport) void func(int argc,char** argv) { int i; for(i=0;i<argc;i++) printf("argv[%d] = '%s'\n",i,argv[i]); } --- x.py ------------ from ctypes import * func = CDLL('x').func func.restype = None func.argtypes = [c_int,POINTER(c_char_p)] def convert(L): return (c_char_p * len(L))(*L) L = ['abc','defghi','jklmnop'] func(len(L),convert(L)) --- OUTPUT --- argv[0] = 'abc' argv[1] = 'defghi' argv[2] = 'jklmnop' -Mark -Mark ------------------------------------------------------------------------------ Oracle to DB2 Conversion Guide: Learn learn about native support for PL/SQL, new data types, scalar functions, improved concurrency, built-in packages, OCI, SQL*Plus, data movement tools, best practices and more. http://p.sf.net/sfu/oracle-sfdev2dev