Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Mallocing and Freeing in C, but passing the pointer through Python via ctypes

I would like to put a malloc a function in C. I would then like to call this function from Python 3.10 via ctypes.DLL. I then would like to free it.

However, I get a segmentation fault. Here’s my very simple C code:

#include <stdlib.h>

struct QueueItem {
    void *value;
    struct QueueItem *next;
};

struct Queue {
    struct QueueItem* head;
    struct QueueItem* tail;
};

struct Queue * new_queue(void * value) {
    struct Queue* queue = malloc(sizeof(struct Queue));

    struct Queue queue_ = { value, NULL };

    return queue;
}

void delete_queue(struct Queue* queue) {
    free(queue);
};

I’ll compile this with gcc -fPIC -shared src/queue.c -o queue.so, and thenn on the python side:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

import ctypes

queue = ctypes.CDLL("./queue.so")

q = ctypes.POINTER(queue.new_queue(1))
print(q)
print(type(q))

queue.delete_queue(q)

But running this will yield:

-1529189344
<class 'int'>
Segmentation fault

The question is, how do I malloc in C, pass the pointer through python, and then free it again in C?.

Primary Resources Consulted:

>Solution :

If you don’t define the restype and argtypes for a function, the restype is assumed to be a C int (c_int), and the argument types are guessed at based on what you pass. The problem here is that the implicit restype of C int is (on a 64 bit system) half the width of a pointer, so the value returned by new_queue is only half of a pointer (which is completely useless).

For safety, and error-checking, you should define both before calling a function, especially the restype which can’t be inferred.

So for your code, you might do:

import ctypes

queue = ctypes.CDLL("./queue.so")

queue.new_queue.argtypes = (c_void_p,)
queue.new_queue.restype = c_void_p

queue.delete_queue.argtypes = (c_void_p,)
queue.delete_queue.restype = None

q = queue.new_queue(1)
print(q)
print(type(q))

queue.delete_queue(q)

Note that passing along 1 as the argument to new_queue is almost certainly incorrect, but I suspect it will work here since none of the code will actually try to use it.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading