python - Cython:如何制作具有不同签名的函数数组
问题描述
在 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
解决方案
我想不出你可以用一组未知类型的函数指针做任何有用的事情——调用它们是不安全的(因为你不知道签名),而且真的没有任何其他事情可做函数指针。因此,您至少需要找到某种方法来存储它是什么类型的指针。
一种选择是存储一个包含两个指针的结构:
cdef struct FuncPtrStruct:
func2param f2p
func3param f3p
然后将一个设置为NULL
,存储在另一个中,并且只调用非NULL
一个 数组规范将类似于cdef FuncPtrStruct array[10]
。
但是,我可能会使用 C Union 来将两个指针存储在同一个内存位置(+ 一个枚举来标识类型)。这需要更多的努力来设置(您需要enum
定义 的类型union
,union
本身,以及struct
包含enum
和的类型union
);但是优点是您可以在不使用更多内存的情况下添加更多不同类型的函数指针(对于“两种类型”的情况,内存可能相等):
# 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 包装器,所以我猜你已经以某种方式列出了这些包装器。如果您想处理 Python 列表FuncPtrHolder
(或以其他方式从 Python 中使用它),您必须将其包装在cdef class
.
在这种情况下,我首选的更简单的解决方案可能是只使用func3param
并让“双参数”函数简单地忽略第三个参数。这意味着所有函数指针都将具有一致的签名,这对我来说更有意义。
推荐阅读
- python - 散列文本文件
- html - 为什么 wordpress 会覆盖引导程序?
- sql - 返回 Case Satment Oracle 中的计数
- c - 在 C 中加密打印不需要的空格。关于为什么的任何想法?
- r - 无法在 Ubuntu 18.04 上的 Microsoft R [MRAN] 4.0.2 上安装 GDINA
- node.js - 有没有办法在 EJS 中包含/渲染变量?
- spring - 在 Spring Cloud Config 中选择特定配置文件时,不返回默认配置文件值
- mysql - Node.js + MySQL:程序拒绝使用“ECONNREFUSED”连接到远程数据库
- vb.net - 比较.image的价值?
- postgresql - 两个并发请求能够锁定 Postgres sql 中的同一行