[issue35390] ctypes not possible to pass NULL c_void_p in structure by reference

Dan report at bugs.python.org
Mon Dec 3 12:11:49 EST 2018


New submission from Dan <dtamayo at astro.princeton.edu>:

I have a C struct 

typedef struct Effect {
    void* ptr;
} Effect;

where when I allocate the memory, the void* gets initialized to NULL, and pass back a pointer:

Effect* get_effect(){
    Effect* pEffect = malloc(sizeof(*pEffect));
    pEffect->ptr = NULL;
    return pEffect;
}

In Python, I need to call the C function to initialize, and then pass a REFERENCE to the pointer to another C function:

from ctypes import cdll, Structure, c_int, c_void_p, addressof, pointer, POINTER, c_double, byref
clibptr = cdll.LoadLibrary("libpointers.so")

class Effect(Structure):
    _fields_ = [("ptr", POINTER(c_double))]

clibptr.get_effect.restype = POINTER(Effect)
pEffect = clibptr.get_effect()
effect = pEffect.contents
clibptr.print_ptraddress(byref(effect.ptr))

But this prints an error, because effect.ptr is None, so byref(None) fails.
Below is full working code in the case where ptr is instead a double*, where there is no problem. 
As far as I can tell, there is no way to pass a c_void_p field by reference, which would be very useful!

#include <stdio.h>
#include <stdlib.h>

#define PRINT_MSG_2SX(ARG0, ARG1) printf("From C - [%s] (%d) - [%s]:  ARG0: [%s], ARG1: 0x%016llX\n", __FILE__, __LINE__, __FUNCTION__, ARG0, (unsigned long long)ARG1)

typedef struct Effect {
    double* ptr;
} Effect;

void print_ptraddress(double** ptraddress){
    PRINT_MSG_2SX("Address of Pointer:", ptraddress);
}

Effect* get_effect(){
    Effect* pEffect = malloc(sizeof(*pEffect));
    pEffect->ptr = NULL;
    print_ptraddress(&pEffect->ptr);
    return pEffect;
}

Python:

from ctypes import cdll, Structure, c_int, c_void_p, addressof, pointer, POINTER, c_double, byref
clibptr = cdll.LoadLibrary("libpointers.so")

class Effect(Structure):
    _fields_ = [("ptr", POINTER(c_double))]

clibptr.get_effect.restype = POINTER(Effect)
pEffect = clibptr.get_effect()

effect = pEffect.contents
clibptr.print_ptraddress(byref(effect.ptr))

gives matching addresses:

>From C - [pointers.c] (11) - [print_ptraddress]: ARG0: [Address of Pointer:], ARG1: 0x00007FC2E1AD3770 From C - [pointers.c] (11) - [print_ptraddress]: ARG0: [Address of Pointer:], ARG1: 0x00007FC2E1AD3770

----------
components: ctypes
messages: 330961
nosy: dtamayo
priority: normal
severity: normal
status: open
title: ctypes not possible to pass NULL c_void_p in structure by reference
type: behavior
versions: Python 3.7

_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue35390>
_______________________________________


More information about the Python-bugs-list mailing list