且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

将C函数作为参数传递给cython中的python函数

更新时间:2023-11-11 16:55:34

如果您要将可调用的任意 Python 作为C函数指针传递,那么它将无法正常工作-无法在标准C语言(因此Cython无法生成代码)。有一个涉及 ctypes 的非常棘手的解决方法(可以执行运行时代码生成,如果需要,我会找到其链接。但是,我并不推荐这样做。

If you want to pass an arbitrary Python callable as a C function pointer then it doesn't work - there's no way to do this in standard C (and thus it's impossible to for Cython to generate the code). There's a very hacky workaround involving ctypes (which can do runtime code generation which I'll find links to if needed. However I don't really recommend it.

如果您很高兴让用户在Cython中编写 cdef 函数(问题暗示您在),那么您可以构建在昨天我对您问题的回答

If you're happy for your users to write cdef functions in Cython (the question implies you are) then you can just build on my answer to your question yesterday.


  1. 编写一个合适的包装器类(您只需要更改函数指针类型)-这将在您编写的 .pxd和.pyx文件之间进行分割。

  1. Write a suitable wrapper class (you just need to change the function pointer type) - this gets split between your .pxd and .pyx files that you write.

让您的用户 cimport ,然后使用它公开其 cdef Python类:

Have your users cimport it and then use it to expose their cdef classes to Python:

from your_module cimport FuncWrapper

cdef int add_c_implementation(int  a, int b):
    return a+b

# `add` accessible from Python
add = WrapperFunc.make_from_ptr(add_c_implementation)


  • 更改 PyClass 以使用 FuncWrapper 作为参数:

    # this is in your_module.pyx
    
    cdef class PyClass:
        def py_wrap(FuncWrapper func, e, f):
            return lambda_c(func.func, e, f)
    


  • 然后,您的用户可以使用Python编译的函数:

  • Your users can then use their compiled functions from Python:

    from your_module import PyClass
    from users_module import add
    
    PyClass().py_wrap(add,e,f)
    







  • 真正的目的是使用一个小的Python包装器来传递一个Python通常无法处理。您对这些包装的函数指针的可能用途非常有限(例如,必须在Cython中设置它们 ),但是它确实提供了选择和传递它们的句柄。


    Really all this is doing is using a small Python wrapper to allow you to pass around a type that Python normally can't deal with. You're pretty limited in what it's possible to do with these wrapped function pointers (for example they must be set up in Cython) but it does give a handle to select and pass them.