Wael Ahmed Elbreqy
Wael Ahmed Elbreqy

Reputation: 21

Cython - Wrapping pointer to structure from C to python

I have a C function which take pointer to struct and i want to use it in python by C-Extensions by Cython way but when i want to pass pointer to struct from python give me an error: "Cannot convert Python object to 'Foo *'" In the below example i make object to call the C function but what passed to C function is NULL pointer.

My Trial:

hello.h

#include <stdio.h>

typedef struct
{
    int x;
} Foo;

int hello(Foo* what);

hello.c

#include "hello.h"

int hello(Foo* what)
{
    printf("Hello Wrapper\n");
    printf("what: %p\n", what);
    what->x = 5;
    return what->x;
}

phello.pxd

cdef extern from "hello.h":
    ctypedef struct Foo:
        int x

    cdef int hello(Foo* what)

phello.pyx

cimport phello

cdef class Foo_c:
    cdef phello.Foo* s

    def hello_fn(self):
        return phello.hello(self.s)

setup.py

from distutils.core import setup, Extension
from Cython.Distutils import build_ext

setup(
cmdclass = {'build_ext': build_ext},
ext_modules=[ Extension("hellomodule",
                         sources=["phello.pyx", "hello.c"],
                       ) ]

test.py

import hellomodule

print "Hello test.py"

tobject = hellomodule.Foo_c()
print "Object:", tobject

tobject.hello_fn()

So i want create "Foo" struct in "test.py" and pass it to "hello_fn()" function to call the C function "hello()" after passing this struct, so i can read or write on this structure from both sides python & C.

Can Anyone help me in this, please?

Upvotes: 2

Views: 1740

Answers (1)

J.J. Hakala
J.J. Hakala

Reputation: 6214

Your code does not allocate memory for phello.Foo. Allocation can be done in __cinit__ with calloc (or malloc) and deallocation in __dealloc__ with free.

cimport phello
from libc.stdlib cimport calloc, free

cdef class Foo_c:
    cdef phello.Foo* s

    def __cinit__(self, int n):
        self.s = <phello.Foo *>calloc(1, sizeof(phello.Foo))

    def __dealloc__(self):
        free(<void *>self.s)

    def __init__(self, int n):
        self.s.x = n

Upvotes: 0

Related Questions