1

Suppose I have the C function which returns void

void mysub_wrapper(int *a, int *b)
{
  *b = *a + 1;
}

Can I make a wrapper with Cython which passes a and b by reference:

cdef extern void mysub_wrapper(int *a, int *b)

def mysub(int a, int b):
  mysub_wrapper(&a, &b)

Such that it can be called in python with

a = 1
b = 0
mysub(a, b)

In other words, can I do the calculation "in place".

nicholaswogan
  • 631
  • 6
  • 13
  • 2
    Python doesn't have the notion of passing variables by reference. In-place operations are only possible on mutable containers, such as lists and dictionaries. – Barmar Oct 15 '21 at 04:28

1 Answers1

1

You can't do this. A cdef-ed function could do it (because it would work solely with C level types, not Python types), but Python level ints are immutable (so you can't actually modify them in-place, you must rebind them to a new int object), and Python has no concept of pass-by-reference (it's pass-by-object-reference, which roughly translates to passing a copy of the pointer, without copying what it points to), so the moment you call mysub(a, b) it makes aliases referring to the same 1 and 0 object that mysub receives, but it loses all connection to the a and b outside the function.

Regardless, it's horribly unPythonic to do this. If you must do it, just have the wrapper allocate its own C level int and pass a pointer to it to the underlying C function, then return the value after it's been reassigned to match Python behavior. The performance cost is meaningless (rewrapping from C int to Python int is chump change in overall overhead of Python), and returning new values rather than modifying function arguments in place, even when it's possible, is much cleaner, less error-prone, and more Pythonic style.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271