Python ctypes 函数指针

4 投票
1 回答
2498 浏览
提问于 2025-04-18 15:11

我创建了一个C语言库,里面有很多函数,我可以通过ctypes在Python中调用这些函数。我对一些简单的函数已经有了一些了解,但对于如何传递正确的参数给下面这个函数,我感到很困惑:

foo(double *, double *, void(*f1)(double *, double *, double, struct sys *),
    void(*f2)(double *, double *, double, struct sys *), struct sys *, double *,
    double, double, int, int, gsl_rng *)

我的起点是为这个函数设置.argtypes。我已经把双精度数组整理好了,比如用POINTER(100*c_double)等等。

不过,我现在卡在了如何传递函数指针这一步。我有几个函数(像f1和f2),它们和foo在同一个库里,我想把它们作为参数传递给foo

我想我已经成功地通过以下代码传递了struct sys*指针:

class sys(Structure):
    _fields_ = [("alpha", c_double),
                ("sigma", c_double)]

然后在这里使用POINTER(sys)作为argtype。最后,gsl_rng是GNU科学库中的一个典型随机数生成器;我不知道从哪里开始处理这个。

有没有人能帮我解释一下复杂的ctypes?

1 个回答

1

在ctypes中,像这样的函数指针类型似乎有点不太存在或者没有文档说明,但你仍然可以使用它们。关键是根本不要定义参数类型

根据ctypes的文档

函数对象默认可以接受任意数量的参数,也可以接受任何ctypes数据实例作为参数……

所以,只要我们不指定参数类型,就可以直接把指针放进去,抱着试试看的态度,这种方法实际上是可行的。下面是一个简单的示例:

f.c:

int f(int n, int (*h)(int)){ return (*h)(n); }
int g(int n){ return n+1; }

f.py:

import ctypes
so = ctypes.CDLL('/path/to/f.so')
f = so.f
g = so.g
print(f(3, g))

输出:

$ gcc -o f.so -shared -fPIC f.c
$ python f.py
4

当然,如果你真的想要ctypes在你指定参数类型时提供的类型检查,那这个方法就不适用了。我不知道有什么办法可以两全其美。

撰写回答