Reputation: 153
I would like to pass a vector by reference to a function in Cython.
cdef extern from "MyClass.h" namespace "MyClass":
void MyClass_doStuff "MyClass::doStuff"(vector[double]& input) except +
cdef class MyClass:
...
@staticmethod
def doStuff(vector[double]& input):
MyClass_doStuff(input)
The above code doesn't throw an error during compilation but it's also not working. input
is simply unchanged after the method.
I have also tried the recommendation in this question but in this case the cdef
-function won't be accessible from Python ("unknown member doStuff...").
Is passing by reference possible and, if so, how to do it properly?
This is not a duplicate of cython-c-passing-by-reference as I refer to the question in the section above. The proposed solution does not accomplish my goal of having a python function taking a parameter by reference.
Upvotes: 4
Views: 3303
Reputation: 30901
The problem
The trouble, as Kevin and jepio say in the comments to your question, is how you handle the vector in Python. Cython does define a cpp vector class, which is automatically converted to/from a list at the boundary to Cython code.
The trouble is that conversion step: when your function is called:
def doStuff(vector[double]& input):
MyClass_doStuff(input)
is transformed to something close to
def doStuff(list input):
vector[double] v= some_cython_function_to_make_a_vector_from_a_list(input)
MyClass_doStuff(input)
# nothing to copy the vector back into the list
The answer(s)
I think you have two options. The first would be to write the process out in full (i.e. do two manual copies):
def doStuff(list input):
cdef vector[double] v = input
MyClass_doStuff(v)
input[:] = v
This will be slow for large vectors, but works for me (my test function is v.push_back(10.0)
):
>>> l=[1,2,3,4]
>>> doStuff(l)
>>> l
[1.0, 2.0, 3.0, 4.0, 10.0]
The second option is to define your own wrapper class that directly contains a vector[double]
cdef class WrappedVector:
cdef vector[double] v
# note the absence of:
# automatically defined type conversions (e.g. from list)
# operators to change v (e.g. [])
# etc.
# you're going to have to write these yourself!
and then write
def doStuff(WrappedVector input):
MyClass_doStuff(input.v)
Upvotes: 3