将C函数作为参数传递给cython中的python函数 [英] Pass c function as argument to python function in cython

查看:186
本文介绍了将C函数作为参数传递给cython中的python函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下有效的代码:

%%cython 

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

cdef int mult(int  a, int b):
    return a*b

ctypedef int (*function_type)(int  a, int b)

cdef int lambda_c(function_type func, int c, int d):
    return func(c,d)

print(lambda_c(add, 5, 6))
print(lambda_c(mult, 5, 6))

所以我有 lambda_c 函数,它将c函数作为参数,但我无法更改它(因为它是c的包装器另一个团队支持的库)。

So I have lambda_c function that takes c function as an argument and I am not able to change it (as it it a wrapper over c library that is supported by another team).

我要做的是写一个包装器:

What I want to do is to write a wrapper:

cdef class PyClass:
    def py_wrap(func, e, f):
        return lambda_c(func, e, f)

print(PyClass().py_wrap(add, 5, 5))
print(PyClass().py_wrap(mult, 6, 6))

但这会引发错误:


无法将Python对象转换为'function_type'

Cannot convert Python object to 'function_type'

我也尝试过强制转换func( return lambda_c(< function_type> func,e,f)),但出现错误:

I also tried to cast func(return lambda_c(<function_type>func, e, f)) but got an error:


Python对象不能转换为原始类型的指针

Python objects cannot be cast to pointers of primitive types

这个想法如下:任何用户都可以在cython中编写自己的函数,对其进行编译,然后导入并将其函数传递给 PyClass( ).py_wrap 方法。

The idea behind this is following: any user will be able to write his own function in cython, compile it and then import and pass his function to PyClass().py_wrap method.

甚至可以导入纯c函数并将其作为参数与cython一起传递吗?

Is it even possible to import pure c function and pass it as a parameter with cython?

看到通过python接口传递cython函数,但与解决方案不同,我无法更改 lambda_c 函数并将其转换为类。此外, lambda_c 仅采用某些类型的函数(在我们的示例中为 function_type

I also saw Pass cython functions via python interface but unlike the solution there I am not able to change lambda_c functon and turn it into a class. Moreover lambda_c takes only functions of certain type (function_type in our example)

推荐答案

如果您要将可调用的任意 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.

    这篇关于将C函数作为参数传递给cython中的python函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆