2

I am struggling to use the concept of pointer in my cython code. The following example is the simplified version of what I am trying to do. I have a function func which I would like to feed in a function (a distribution function) as an input parameter. The distribution has two pointer vectors as input variables.

from cpython cimport array
import cython
import ctypes
cimport numpy as np

ctypedef void (*myFuncDef)(double *, double *)
from cython.parallel import prange
cdef void func(int* x, double* hx, void(*func)(double*, double*), int n):
      def int i
      for i from 0 <= i < n:
          func[0](&x[i], &hx[i])
      return

cpdef void Lognormal(double* u, 
                  double* yu):
      #evaluate log of normal distribution
      yu=-u*u*0.5
      return

def foo(np.ndarray[ndim=1, dtype=np.float64_t] x,
        np.ndarray[ndim=1, dtype=np.float64_t] hx,
        myFuncDef distribution, int k):
    cdef np.ndarray[ndim=1, dtype=np.float64_t] sp
    cdef int num=len(x)
    cdef int j
    for j from 0 <= j <k:
        func(&x[0],&hx[0],&distribution, num)
        sp[j]=hx[0]
    return sp

So I would like to used the Lognormal function as an input for foo function. I get the following error message:

Cannot assign type 'myFuncDef *' to 'void (*)(double *, double *)'

I will appreciate for any suggestion to fix this bug.

mch
  • 9,424
  • 2
  • 28
  • 42
Dalek
  • 4,168
  • 11
  • 48
  • 100
  • Your code has a lot of compiler errors, so maybe you should start small, compiling one function after another. `myFuncDef distribution` does not work? So don't use the fancy ctypedef, use directly `void (*distribution)(double *, double *)`. When everything compiles, you can go back and add syntactic sugar. – ead Sep 22 '17 at 19:00
  • @ead when I compile foo function with your suggestion change I get this error:Cannot convert Python object argument to type `void (*)(double *, double *)` because it is a `python` function, any other suggestion to fix this bug? – Dalek Sep 22 '17 at 22:11
  • So maybe `foo` cannot be a python-function but must be `cdef`? – ead Sep 23 '17 at 05:09
  • @ead `foo` function is the main function that I want to import in my python code, if I'd define it as `cdef` function, then it is not accessible for python, is it? – Dalek Sep 24 '17 at 08:34
  • @ead Do you have any suggestion to fix `foo` function in order to be able to pass a pointer function as its argument? – Dalek Sep 24 '17 at 13:10
  • It's hard to make a suggestion based on your question. There is no such thing as a function pointer in python - all functions are objects. But feel free to ask a new question with would provide a better description and a minimal example (because now it is far from minimal). – ead Sep 24 '17 at 13:49
  • @ead well I can not make it more simpler than what it is right now. – Dalek Sep 24 '17 at 15:03
  • @ead I posted another question to solve my problem [here](https://stackoverflow.com/questions/46423468/pass-different-c-functions-with-pointer-arrays-as-it-argument-to-a-class). Any thoughts? – Dalek Sep 26 '17 at 10:06

1 Answers1

2

You have one too many layers of pointer (the standard issue raised to argue against typedefs for pointers). Just drop the & from &distribution; it's already the function pointer you want.

Davis Herring
  • 36,443
  • 4
  • 48
  • 76
  • Thanks for the answer. It resolves that bug but I get new error message regarding `foo` function as follows: `Cannot convert Python object argument to type 'myFuncDef'`. Any suggestion to get rid of this? – Dalek Sep 22 '17 at 11:27
  • `Error compiling Cython file: def foo(np.ndarray[ndim=1, dtype=np.float64_t] x, np.ndarray[ndim=1, dtype=np.float64_t] hx, myFuncDef distribution, int k):` – Dalek Sep 22 '17 at 11:36
  • would you please clarify how I should define function `distribution` in the `foo` function in order that it won't raise error message? Thanks – Dalek Sep 22 '17 at 18:26
  • I'm afraid that's beyond my expertise here. You might want to ask a new question (if the discussion with ead isn't enough). – Davis Herring Sep 23 '17 at 05:55