Ivan Mishalkin
Ivan Mishalkin

Reputation: 1108

Is it possible to define c-type variable in python and pass its address to cython wrapped function

I am wrapping a C-library with Cython and for now I do not know how to workaround passing address to C function from python. Details below:

I have some C-function that takes address to some defined beforehand C variable and changes its value:

void c_func(int* x) {
*x=5;
}

As a C user I can use this function in following way:

def int var1
def int var2
c_func(&var1)
c_func(&var2)

After execution both var1 and var2 will be equal to 5. Now I want to wrap c_func with cython. I'd like to have py_func that might be imported from wrapper package and used, but I do not know how to define c variables from python.

What I have already done(in jupyter):

%load_ext cython

%%cython

cdef int some_int

cdef extern from *:
    """
    void c_func(int* x) {
    *x=5;
    }

    """
    int c_func(int* x)

c_func(&some_int)

print(some_int)

What I want to get:

%%cython

# This part should be in separate pyx file
cdef extern from *:
    """
    void c_func(int* x) {
    *x=5;
    }

    """
    int c_func(int* x)

def py_func(var):
    c_func(&var)

# The following part is user API
from wrapper import py_func

var_to_pass_in_py_func = ... # somehow defined C variable

py_func(var_to_pass_in_py_func) 

print(var_to_pass_in_py_func) # should print 5

var_to_pass_in_py_func might not be converted to python object, but C functions wrapped with python should not conflict with it.

Is it possible?

Upvotes: 0

Views: 206

Answers (1)

oz1
oz1

Reputation: 998

I have no idea how your example makes sense in practice, but one possible way is to pass a buffer, which managed by python, to the C function. For example:

%%cython -a -f 

# Suppose this is the external C function needed to wrap
cdef void c_func(int* value_to_change):
    value_to_change[0] = 123;

def py_func(int[:] buffer_to_change):
    c_func(&buffer_to_change[0]);

from array import array
from ctypes import *

a = array('i', [0]);
py_func(a)
print(a[0])

b = (c_int*1)() # c_int array with length 1
py_func(b)
print(b[0])

Upvotes: 1

Related Questions