2

I have a C function that takes a function as an input. I would like to to be able to call this from python. The final goal is to have the input function be defined in python but evaluated in C. At the moment I'm just trying to get a toy example working. So here's what I've done...

  1. I have a header file that I call 'Test.h'. There is one function here that simply evaluates a function with two arguments.

    #include <stdio.h>
    
    double cEval( double ( *f )( double, double ), double n, double m ){
        double k1 = f( n, m );          
        return k1;
    };
    
  2. I then wrote a cython file to wrap my function. This file is called 'Test.pyx'.

    cdef extern from "Test.h":
        double cEval( double ( *f )( double, double ), double n, double m )
    
    def Eval( f, n, m ):
        return cEval( f, n, m )
    
  3. Finally, I wrote the setup file.

    from distutils.core import setup, Extension
    from Cython.Build import cythonize
    
    setup(ext_modules=cythonize('Test.pyx'))
    
  4. I then compile 'setup.py' using the command 'python setup.py build_ext --inplace', which returns the following error:

    Compiling Test.pyx because it changed.
    [1/1] Cythonizing Test.pyx
    /usr/lib64/python2.7/site-packages/Cython/Compiler/Main.py:367: FutureWarning: Cython directive 'language_level' not set, using 2 for now (Py2). This will change in a later release! File: /maybehome/jritchie/c_interaction_example/Fun_Input/Test.pyx
      tree = Parsing.p_module(s, pxd, full_module_name)
    
    Error compiling Cython file:
    ------------------------------------------------------------
    ...
    cdef extern from "Test.h":
            double cEval( double ( *f )( double, double ), double n, double m )
    
    def Eval( f, n, m ):
            return cEval( f, n, m )              ^
    ------------------------------------------------------------
    
    Test.pyx:5:15: Cannot convert Python object to 'double (*)(double, double)'
    Traceback (most recent call last):
      File "setup.py", line 4, in <module>
        setup(ext_modules=cythonize('Test.pyx'))
      File "/usr/lib64/python2.7/site-packages/Cython/Build/Dependencies.py", line 1086, in cythonize
        cythonize_one(*args)
      File "/usr/lib64/python2.7/site-packages/Cython/Build/Dependencies.py", line 1209, in cythonize_one
        raise CompileError(None, pyx_file)
    Cython.Compiler.Errors.CompileError: Test.pyx
    

Does anyone know what I am doing wrong and how I can fix this?

zx485
  • 28,498
  • 28
  • 50
  • 59
  • This isn't _really_ possible in Cython. See the second-half of [this answer](https://stackoverflow.com/questions/34878942/using-function-pointers-to-methods-of-classes-without-the-gil/34900829#34900829) for a workround. The function you pass won't be "evaluated in C" though. I'm struggling to find a good duplicate for this right now, but I'm pretty sure there is one – DavidW Jan 20 '19 at 22:26
  • 2
    Possible duplicate of [Making a Cython wrapper around Python function](https://stackoverflow.com/questions/51044122/making-a-cython-wrapper-around-python-function) – DavidW Jan 20 '19 at 22:30

0 Answers0