Mailing List Archive

Help on ctypes.POINTER for Python array
Hi,

Need some help,

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)

Thanks
Jason
--
https://mail.python.org/mailman/listinfo/python-list
Re: Help on ctypes.POINTER for Python array [ In reply to ]
I’m not sure this is the shortest method, but you could set up two python scripts to do the same thing and convert them to c using cython. I wouldn’t be able to read the c scripts, but maybe you could.

Maybe someone else has a more direct answer.

Sent from my iPhone

> On May 11, 2023, at 10:00 AM, Jason Qian via Python-list <python-list@python.org> wrote:
>
> ?Hi,
>
> Need some help,
>
> 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)
>
> Thanks
> Jason
> --
> https://mail.python.org/mailman/listinfo/python-list

--
https://mail.python.org/mailman/listinfo/python-list
Re: Help on ctypes.POINTER for Python array [ In reply to ]
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
Re: Help on ctypes.POINTER for Python array [ In reply to ]
Awesome, thanks!

On Thu, May 11, 2023 at 1:47?PM Eryk Sun <eryksun@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