I'm using ctype
to call C code from Python.
The C function I need to call takes a char***
, and so it's bind as using a ctypes.POINTER(ctypes.POINTER(ctypes.c_char))
.
I don't understand how I should safely create and initialize such objects, because if I create one and immediatly try to iterate it, the Python program crashs:
import ctypes
names = ctypes.POINTER(ctypes.POINTER(ctypes.c_char))()
if names != None:
for name in names:
pass
Error is:
Traceback (most recent call last):
File "example_sdetests_lib_bind_python_string_array.py", line 6, in <module>
for name in names:
ValueError: NULL pointer access
How can I safely check a ctypes.POINTER(ctypes.POINTER(ctypes.c_char))
is NULL or not?
I'm using ctype
to call C code from Python.
The C function I need to call takes a char***
, and so it's bind as using a ctypes.POINTER(ctypes.POINTER(ctypes.c_char))
.
I don't understand how I should safely create and initialize such objects, because if I create one and immediatly try to iterate it, the Python program crashs:
import ctypes
names = ctypes.POINTER(ctypes.POINTER(ctypes.c_char))()
if names != None:
for name in names:
pass
Error is:
Traceback (most recent call last):
File "example_sdetests_lib_bind_python_string_array.py", line 6, in <module>
for name in names:
ValueError: NULL pointer access
How can I safely check a ctypes.POINTER(ctypes.POINTER(ctypes.c_char))
is NULL or not?
1 Answer
Reset to default 1FYI: char***
does need three ctypes.POINTER
.
To test for null, test like any other "falsey" object:
import ctypes as ct
# define char*** type
PPPCHAR = ct.POINTER(ct.POINTER(ct.POINTER(ct.c_char)))
# instantiate (default null)
names = PPPCHAR()
if not names:
print('NULL')
# Simple initialization
c = ct.c_char(b'a')
# pointer(obj) creates a ctypes pointer instance to a ctypes object.
pc = ct.pointer(c)
ppc = ct.pointer(pc)
pppc = ct.pointer(ppc)
if pppc:
print('non-NULL')
print(pppc.contents.contents.contents)
Output:
NULL
non-NULL
c_char(b'a')
char***
is a 3-star pointer. Don't you needctypes.POINTER(ctypes.POINTER(ctypes.POINTER(ctypes.c_char)))
? (i.e. another level) – wohlstad Commented Jan 17 at 17:39char***
that you mentioned is a pointer-to-pointer-to-pointer-to-char (3 levels), and not just a a pointer-to-pointer-to-char (2 levels). – wohlstad Commented Jan 17 at 19:18names = ctypes.POINTER(ctypes.POINTER(ctypes.POINTER(ctypes.c_char)))()
, thenfor name in names:
produces the same crash. – jpo38 Commented Jan 17 at 21:38bool(names)
orif names: ...
to check for a null pointer. Much like C pointers. How to initialise is a more complicated question. Depends on what you want to initialise the value as, and who is meant to own and manage the memory allocation (C or Python) – Dunes Commented Jan 17 at 23:16