33

我有一堆用 C 编写的函数,我想要一些用 Python 编写的代码来访问这些函数。

我在这里阅读了几个处理类似问题的问题(例如这里这里),但我对需要采用哪种方法感到困惑。

一个问题推荐 ctypes,另一个问题推荐 cython。我已经阅读了两者的一些文档,但我完全不清楚哪个更适合我。

基本上我已经编写了一些 python 代码来执行一些二维 FFT,我希望 C 代码能够看到该结果,然后通过我编写的各种 C 函数对其进行处理。我不知道从 C 调用 Python 是否更容易,反之亦然。

4

4 回答 4

64

您应该通过编写ctypes包装器从 Python 调用 C。Cython 用于使类似 python 的代码运行得更快,ctypes 用于使 C 函数可从 python 调用。您需要执行以下操作:

  1. 编写要使用的 C 函数。(你可能已经这样做了)
  2. 为这些函数创建一个共享对象(.so,用于 linux、os x 等)或动态加载的库(.dll,用于 Windows)。(也许你也已经这样做了)
  3. 编写 ctypes 包装器(这比听起来容易,我为此写了一个操作方法
  4. 在 Python 中从该包装器调用一个函数。(这就像调用任何其他 python 函数一样简单)
于 2013-05-20T10:52:41.633 回答
10

如果我理解得很好,你不喜欢像 c => python 或 python => c 那样进行对话。在那种情况下,我会推荐Cython. 它对多种操作非常开放,特别是在您的情况下,从 C 调用一个用 Python 编写的函数。

这是它的工作原理(public api):

下面的例子假设你有一个 Python 类(self是它的一个实例),并且这个类有一个method你想在这个类上调用的方法(name)并处理double来自 C 的结果(这里是 a)。这个函数,写在一个Cython extension会帮助你做这个调用。

cdef public api double cy_call_func_double(object self, char* method, bint *error):
    if (hasattr(self, method)):
        error[0] = 0
        return getattr(self, method)();
    else:
        error[0] = 1

在 C 端,您将能够像这样执行调用:

PyObject *py_obj = ....
...
if (py_obj) {
    int error;
    double result;
    result = cy_call_func_double(py_obj, (char*)"initSimulation", &error);
    cout << "Do something with the result : " << result << endl;
}

Python/C API 提供的PyObjecta在哪里捕获(通过转换常规 python ,在你的 cython 扩展中像这样 : ),你最终可以调用它的方法并对结果做一些事情。(这里是, 但 Cython 可以轻松处理, , ...structpy_objobject<PyObject *>my_python_objectinitSimulationdoublevectorssets

Well, I am aware that what I just wrote can be confusing if you never wrote anything using Cython, but it aims to be a short demonstration of the numerous things it can do for you in term of merging.

By another hand, this approach can take more time than recoding your Python code into C, depending on the complexity of your algorithms. In my opinion, investing time into learning Cython is pertinent only if you plan to have this kind of needs quite often...

Hope this was at least informative...

于 2013-05-20T15:36:20.337 回答
4

Well, here you are referring to two below things.

  1. How to call c function within from python (Extending python)
  2. How to call python function/script from C program (Embedding Python)

For #2 that is 'Embedding Python'

You may use below code segment:

#include "python.h"

int main(int argc, char *argv[]) {   
Py_SetProgramName(argv[0]);  /* optional but recommended */   
Py_Initialize();   
PyRun_SimpleString("from time import time,ctime\n"
    "print 'Today is',ctime(time())\n");
/*Or if you want to run python file within from the C code*/       
//pyRun_SimpleFile("Filename");    
Py_Finalize();   
return 0; }

对于#1,即“扩展 Python”, 那么最好的办法是使用 Ctypes(顺便说一句,可在所有 python 变体中移植)。

从 ctypes 导入 *

libc = cdll.msvcrt

打印 libc.time(无)

1438069008

printf = libc.printf

printf("你好,%s\n", "世界!")

你好世界!14

printf("%d 瓶啤酒\n", 42)

42 瓶啤酒 19

有关详细指南,您可能需要参考我的博客文章

于 2015-08-28T06:44:22.877 回答
2

从python调用C会更容易。你的场景听起来很奇怪——通常人们用 python 编写大部分代码,除了处理器密集型部分,它是用 C 编写的。二维 FFT 是代码的计算密集型部分吗?

于 2013-05-20T10:44:23.253 回答