Cython:如何创建一个具有不同签名的函数数组

2024-04-25 13:09:55 发布

您现在位置:Python中文网/ 问答频道 /正文

在Cython中,我想存储一个函数数组,但是这些函数并不是都有相同的签名。具体来说,有些有两个参数,有些有三个。你知道吗

我定义如下:

ctypedef long (*func2param)(long param1, long param2)
ctypedef long (*funct3param)(long param1, long param2, long param3)

然而,即使我只有一个这样的签名,我仍然不知道如何让它工作。尝试将cdef函数分配给上述类型之一的数组会导致:

func_array2[i] = func_list[i][FUNCTION]

Cannot convert Python object to 'func2param'

尝试施展:

func_array2[i] = <func2param>func_list[i][FUNCTION]

Python objects cannot be cast to pointers of primitive types

Tags: to函数参数定义function数组cythonlong
1条回答
网友
1楼 · 发布于 2024-04-25 13:09:55

对于未知类型的函数指针数组,我想不出有什么有用的方法—调用它们是不安全的(因为您不知道签名),而且函数指针真的没有任何其他方法可以做。因此,您至少需要找到存储指针类型的方法。你知道吗

一种选择是存储包含两个指针的结构:

cdef struct FuncPtrStruct:
    func2param f2p
    func3param f3p

然后将其中一个设置为NULL,存储在另一个中,并且只调用非NULL的一个,然后数组规范将类似于cdef FuncPtrStruct array[10]。你知道吗

不过,我可能会使用C联合来将两个指针存储在同一个内存位置(使用枚举标识类型)。这需要更多的设置(您需要一个enum来定义union的类型,union本身,以及包含enumunionstruct);但是,优点是可以添加更多不同类型的函数指针,而无需使用更多内存(对于“两种类型”的情况,内存可能相等):

# cpdef if you want to use the enum from Python too
cdef enum FuncType:
    twoArg, threeArg

cdef union FuncPtrUnion:
    func2param f2p
    func3param f3p

cdef struct FuncPtrHolder:
    FuncType type_
    FuncPtrUnion value

只是为了说明你是如何使用它的:

cdef long f(long x1, long x2):
    print("f",x1,x2)
    return 0

cdef long g(long x1, long x2, long x3):
    print("g",x1,x2,x3)
    return 1

def example():
    cdef FuncPtrHolder fArray[10]
    for i in range(10):
        if i%2:
            fArray[i].type_ = twoArg
            fArray[i].value.f2p = &f
        else:
            fArray[i].type_ = threeArg
            fArray[i].value.f3p = &g
    # use
    for i in range(10):
        if fArray[i].type_ == twoArg:
            fArray[i].value.f2p(i,i+1)
        elif fArray[i].type_ == threeArg:
            fArray[i].value.f3p(i,i+1,i+2)

看起来在代码中有一些list的Python对象,这就是为什么会出现编译错误。没有代码是不可能知道为什么的,但是我认为Cython可以自动为cdef函数生成Python包装器,所以我猜您已经列出了这些包装器。如果要处理FuncPtrHolder的Python列表(或者从Python中使用它),则必须将其包装在cdef class中。你知道吗


在本例中,我的首选、更简单的解决方案可能是只使用func3param,让“双参数”函数忽略第三个参数。这意味着所有的函数指针都有一个一致的签名,这对我来说更有意义。你知道吗

相关问题 更多 >