Cython - 实现回调 [英] Cython - implementing callbacks

查看:182
本文介绍了Cython - 实现回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用Cython尝试与用c ++编写的库接口。到目前为止事情都很好,我可以有效地使用库中的MOST函数。我唯一的问题在于实现回调。该库有4个函数定义,看起来像这样:

I have been working with Cython in an attempt to interface with a library written in c++. So far things are going pretty good, and I can effectively use MOST functions within the library. My only problem lies within implementing callbacks. The library has 4 function definitions that look a little something like this:

typedef void (*Function1)(const uint16_t *data, 
                         unsigned width, unsigned height);
void SetCallBack(Function1);

因此,为了实现它们,我想使用cython做这样的事情:

So to implement them I figured I would do something like this with cython:

ctypedef void (*Function1)(unsigned short *data, 
                         unsigned width, unsigned height);
cdef extern from "lib.hpp":
    void SetCallBack(Function1)

其中实际编译正确,但是,我不能为我的生活思考如何实际实现,以这种方式回调将工作。我第一次尝试创建一个函数,只是调用它,类似于你将如何做任何其他函数,提出这样:

Which actually compiles correctly, however, I can't for the life of me think how to actually implement that in such a way that the callback would work. I first tried creating a function that would just call that, similar to how you would do it for any other function, coming up with this:

def PySetCallBack(Func):
    SetCallBack(Func)

(可预测)错误:

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

"Cannot convert Python object to 'Function1'"

我在哪里。如果任何人有任何经验设置回调在Cython中,我将非常感谢任何帮助。感谢。

so yeah, that's where I'm at. If anyone has any experience setting up callbacks in Cython I would be very grateful for any assistance. Thanks.

编辑
根据您的建议,我使用cdef创建了一个中间函数, p>

Edit: Following your advice, I created an intermediate function with a cdef, which looks like this:

cdef void cSetCallBack(Function1 function):
    SetCallBack(function)

这似乎让我...密切?现在至少得到一个不同的错误:

This seems to have gotten me... Closer? Getting a different error now at least:

error: invalid conversion from ‘void (*)(short unsigned int*, unsigned int, unsigned int)’ to ‘void (*)(const uint16_t*, unsigned int, unsigned int)’



<

Now, far as I can tell those types are identical, so I can't figure what's going on.

Edit2
通过声明一个新的typedef解决了这个问题:

Edit2: Fixed that problem by declaring a new typedef:

ctypedef unsigned short uint16_t

并使用它作为参数调用,但显然没有实际上越来越近,但只是带我在一个侧轨,调用该函数,我得到相同的无法转换Python对象到'Function1'错误了。

and using that as the argument to call, but apparently that wasn't actually getting any closer, but just taking me around a side track, since when trying to call that function, I get the same "Cannot convert Python object to 'Function1'" error all over again.

所以,我几乎回到我开始。只有我现在可以做的事情是显式地转换为ac函数作为ac函数,像这样,但是,老实说,我不知道我会怎么走。

So, I'm pretty much back where I started. Only thing I can figure to do now is explicitly cast the python object coming in as a c function like that, but, to be honest, I have no idea how I would go about that.

编辑第三个
好​​吧,解剖你的答案后,我终于得到它,它的工作原理,所以hooray和whatnot。我最后做的是创建一个这样的函数:

Edit the third: Alright, after dissecting your answer I finally get it, and it works, so hooray and whatnot. What I ended up doing was creating a function like this:

cdef void cSetCallback(Function1 function):
    SetCallback(function)
cdef void callcallback(const_ushort *data, unsigned width, unsigned height):
    global callbackfunc
    callbackfunc(data,width,height)
cSetCallback(callcallback)
def PySetCallback(callbackFunc):
    global callbackfunc
    callbackfunc = callbackFunc

现在唯一的问题是它不能将const_ushort *数据转换为一个python对象,但这是另一个问题,所以我想这个是解决了,非常感谢。

So now the only problem is that it can't convert const_ushort *data into a python object, but that's another problem entirely, so I guess this one is solved, thanks a lot.

推荐答案

如果你可以修改库来定义:

If you can modify the library to define:

typedef void (*Function1)(const uint16_t *data, 
                          unsigned width, unsigned height,
                          void *user_data);
void SetCallBack(Function1, void*);

,我怕你不幸运。如果你有 void * ,你定义一个函数调用带有正确参数的python可调用对象和 SetCallBack 这个函数和python可调用。

instead, I fear you are out of luck. If you have the void*, than you define a function that calls a python callable object with correct arguments and SetCallBack with this function and the python callable.

如果你不能,但回调是全局的(似乎是),你可以创建一个全局变量来存储python对象。再次创建一个函数来调用python对象,并将它传递给 SetCallBack 和你的 PySetCallback

If you can't, but the callback is global (it seems to be), you can create a global variable to store the python object in. Than you'd again create a function to call the python object and pass it to SetCallBack and your PySetCallback would just set the global and ensure proper function is registered.

如果回调是上下文特定的,但你没有办法传递一个用户数据指针,

If the callback is context-specific, but you have no way to pass it a "user data" pointer, I fear you are out of luck here.

我知道python和C ++,但不是cython,所以我不知道你是否可以在cython中创建函数,是否必须用C ++编写。

I know python and C++, but not cython, so I don't know whether you can create the function in cython, or whether you'd have to write in C++.

这篇关于Cython - 实现回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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