简体   繁体   中英

Wrap a double** c++ function with cython

I have a C++ function which returns a pointer double** - a high dimensional matrix in particular - and I'd like to wrap it to some python code using Cython. How should I act?

Here an example with a function with a double* pointer for sake of simplicity.

My C++ fib.cpp code:

double add(double a, double b)
{
 return a+b;
}

double p[]= {1,2,3,4}; 

double* mult(double a)    
{
p[0]=p[0]*a;
p[1]=p[1]*a;
return p; 
}

Then there is the fib.hpp file:

double add(double a,double b);
double* mult(double a);

Then the pxd file fib.pxd :

cdef extern from "fib.hpp":
     double add(double a,double b);
     double* mult(double a);

In the end the pyx file

# distutils: language = c++
# distutils: sources = fib.cpp 

cimport fib 

def add(a,b):
    return fib.add(a,b)
def mult(a):           # dropping these lines
    return fib.mult(a) # the code works without the double* function

Everything is compiled with the rather standard setup.py :

from distutils.core import setup, Extension
from Cython.Build import cythonize

ext = Extension("fib2cpp",
            sources=["fib.pyx", "fib.cpp"],
            language="c++")

setup(name="fib",
ext_modules=cythonize(ext))

When I compile the code:

setup.py build_ext -if

Cannot convert ' double * ' to python object.

When I try with a double** function I get the same error. What should I do?

I have found a solution for the case double * . First of all, the file fib.pxd is useless. Then we need a new fib.pyx file:

# distutils: language = c++
# distutils: sources = fib.cpp


import numpy as np 
cimport numpy as cnp 



cdef extern from "fib.hpp":
     double fib(int n)
     double add (double a, double b)
     double* mult(double a)



def make_mult(double a):
    cdef double[:] mv = <double[:4]> mult(a) # the 4 stands for
    return np.asarray(mv)   # the dimension of the array defined in fib.cpp 

In the case of a function which returns a nrows*ncols matrix; such as double* make_mat(int nrows, int ncols) , the second line of the function make_mult has to be rewritten as:

cdef double[:,:] mv=<double[:nrows,:ncols]> make_mat(nrows, ncols) 

Regrettably, If I have a function double** make_mat(int nrows, int ncols) which always returns a matrix, then the previous code rises the error :

Pointer base type does not match cython.array base type

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM