Cython : How wrap C function that takes a void* pointer / how to call it from python
Question: i'am trying to wrap some functions defined in a dll using Cython , the
difficulty is that lots of this functions use pointers to void* , here is an
example of functions prototype :

    
    
    ---------------"header.h"-----------------------
    
    typedef void* HANDLE
    
    int open(HANDLE* a_handle_pointer , int open_mode)
    
    int use(HANDLE a_handle, int usage_mode )
    

the usage example in C is :

    
    
    ---------------"main.c" -----------------
    
    #include"header.h"
    
    HANDLE my_handle ;
    int results ;
    if(open(&my_handle ,1) == 0) /* open a handle with mode 1 */
    {
        printf ("failed to open \n);
        return 0;
    }
    
    else printf("open success \n");
    
    use(handle , 2); /* use handle (opened with open) in mode 2 */
    

As you can remark , the "Use" function can't do something unless the Handle
had already been opened using the "open" function , which makes it confusing
in python/cython

Here is how I define my function "open" in Cython (one of several trials )

    
    
    from libc.stdint cimport uintptr_t
    cdef extern from "header.h":
         ctypedef void*     HANDLE 
         int open(HANDLE* a_handle_pointer , int open_mode)
    
    
    def Open( uintptr_t a_handle_pointer , int open_mode)
    
        return open(<HANDLE*> a_handle_pointer , open_mode)
    

I have tried to cast void * pointer to uintptr_t as some people advise, but
still get the error : " TypeError: an integer is required " when calling the
function.

    
    
    >>>from my_module import open
    >>>open (handle , 1)
    

How would you do to solve this problem ?

I'am wondering how would I call a function from python with an argument of
type void* or void** ?

your propositions and answers are welcome !!


Answer: Writing the module/binding in Python itself is a _bad_ idea, specially if
pointers are involved. You should rather do it in C with something like
this... **Warning** : This is specific to CPython 3+. CPython 2 extensions are
coded differently! **BTW** : Renamed your `open` function as `load` because it
conflicts with POSIX's [`open(3)`](http://linux.die.net/man/3/open).

    
    
    // my_module.c: My Python extension!
    
    /* Get us the CPython headers.
     */
    #include "Python.h"
    
    /* And your function's headers, of course.
     */
    #include "header.h"
    
    /* Actual structures used to store
     * a 'my_module.Handle' internally.
     */
    typedef struct
    {
        PyObject_HEAD /* The base of all PyObjects. */
        HANDLE handle; /* Our handle, great! */
    } my_module_HandleObject;
    
    /* The type 'my_module.Handle'. This variable contains
     * a lot of strange, zero, and NULLified fields. Their
     * purpose and story is too obscure for SO, so better
     * off look at the docs for more details.
     */
    static PyTypeObject my_module_HandleType =
    {
        PyVarObject_HEAD_INIT(NULL, 0)
        "my_module.Handle", /* Of course, this is the type's name. */
        sizeof(my_module_HandleObject), /* An object's size. */
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ... Don't ask. */
        Py_TPFLAGS_DEFAULT, /* The type's flags. There's nothing special about ours, so use the defaults. */
        NULL /* No docstrings for you! */
    };
    
    /* The "wrapper" function. It takes a tuple of
     * CPython PyObject's and returns a PyObject.
     */
    static PyObject *my_module_load(PyObject *self, PyObject *args)
    {
        int load_mode;
        if(!PyArg_ParseTuple(args, "i", &load_mode) != 0) { /* Parse the argument list. It should have one single integer ("i") parameter. */
            return NULL;
        }
    
        /* Create a Handle object, so as to put
         * in itthe handle we're about to get.
         */
        my_module_HandleObject *the_object = PyObject_New(my_module_HandleObject, &my_module_HandleType);
        if(the_object == NULL) {
            return NULL;
        }
    
        /* Finally, do our stuff.
         */
        if(load(&the_object->handle, load_mode) == -1) {
            Py_DECREF(the_object);
            PyErr_SetFromErrno(NULL);
            return NULL;
        }
    
        return (PyObject*)the_object;
    }
    
    /* The method table. It is a list of structures, each
     * describing a method of our module.
     */
    static struct PyMethodDef my_module_functions[] =
    {
        {
            "load", /* The method's name, as seen from Python code. */
            (PyCFunction)my_module_load, /* The method itself. */
            METH_VARARGS, /* This means the method takes arguments. */
            NULL, /* We don't have documentation for this, do we? */
        }, { NULL, NULL, 0, NULL } /* End of the list. */
    };
    
    /* Used to describe the module itself. */
    static struct PyModuleDef my_module =
    {
        PyModuleDef_HEAD_INIT,
        "my_module", /* The module's name. */
        NULL, /* No docstring. */
        -1,
        my_module_functions,
        NULL, NULL, NULL, NULL
    };
    
    /* This function _must_ be named this way
     * in order for the module to be named as
     * 'my_module'. This function is sort of
     * the initialization routine for the module.
     */
    PyMODINIT_FUNC PyInit_my_module()
    {
        my_module_HandleType.tp_new = PyType_GenericNew; /* AFAIK, this is the type's constructor. Use the default. */
        if(PyType_Ready(&my_module_HandleType) < 0) { // Uh, oh. Something went wrong!
            return NULL;
        }
    
        PyObject *this_module = PyModule_Create(&my_module); /* Export the whole module. */
        if(this_module == NULL) {
            return NULL;
        }
    
        Py_INCREF(&my_module_HandleType);
        PyModule_AddObject(this_module, "Handle", (PyObject*)&my_module_HandleType);
    
        return this_module;
    }
    

In order to build and install the extension, [see the docs on
`distutils`](https://docs.python.org/2/extending/building.html#building).

