Cython:未定义符号

时间:2018-07-10 18:46:56

标签: python cython

我编写了一个最小的C函数(带有附带的头文件),目的是创建一个Cython包装器,该包装器将允许其他地方的Python文件使用C代码。

我的文件是这样的:

C文件:

/* engine.c */

#include <stdio.h>
#include "customlib.h"

int engine(int value, int iterations) {

    /* declare iteration index */
    int idx;

    for (idx = 0; idx < iterations; idx = idx + 1) {
        value = value * 3;
    }

    /* return value that should be accessible by the Python module */
    return value;
}

C头文件:

/* customlib.h */

#ifndef CUSTOM_HEADER_H
#define CUSTOM_HEADER_H

/* engine function */
int engine(int value, int iterations);

#endif

包装C代码的Cython模块:

# wrapper.pyx

cdef extern from "customlib.h":
    int engine(int value, int iterations)

def call_c_code(value, iterations):
    output_value = engine(value, iterations)
    print(output_value)

通过Cython包装器调用C代码的Python模块:

# caller.py

import wrapper

wrapper.call_c_code(1, 2) /* values not important; just an example */

用于从* .pyx文件生成* .so的设置代码:

# setup.py

from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize

# definitions
sourcefiles = ['engine.c']
extensions = [Extension('wrapper', sourcefiles)]

# setup function
setup(name='wrapper', ext_modules=cythonize('wrapper.pyx'))

问题:共享对象(* .so)似乎可以正常编译。但是,即使仅导入wrapper.py也会引发以下错误:

Traceback (most recent call last):
  File "caller.py", line 10, in <module>
    import wrapper
ImportError: /home/alex/Documents/Projects/Cython/wrapper.cpython-36m-x86_64-linux-gnu.so: undefined symbol: engine

1 个答案:

答案 0 :(得分:0)

在您的setup.py中,您实际上没有做任何事情:

extensions = [Extension('wrapper', sourcefiles)]

本质上,这只是死代码。它分配给变量,然后从不使用它。无论如何,您都不想从Extension中创建一个engine.cExtension用于定义Python模块。这里唯一的Python模块是从wrapper.pyx编译而来的模块。

相反,请尝试以下操作:

extensions = [Extension('wrapper', ['wrapper.pyx', 'engine.c'])]
setup(
    ...
    ext_modules=cythonize(extensions)
    ...
 )

这还将编译engine.c并将其生成的目标文件链接到您的扩展模块中。

cythonize辅助函数足够聪明,可以将纯.c源与需要通过Cython编译器传递的Cython源区分开。然后它将所有产生的C源代码通过C编译器传递并链接它们。