我在mac OS X 10.10.2上使用Python3。我是python C-API的新手,所以我正在尝试"Python Cookbook"http://chimera.labs.oreilly.com/books/1230000000393/ch15.html 中的C-API扩展的简单示例。我认为 Python2 和 Python3 之间有一些区别。我遵循了 Python3 文档,但找不到为什么我的案例不起作用。
直到用蒸馏作品(python3 setup.py build
或python3 setup.py build_ext --inplace
)构建,给我sample.so
文件。我编译了sample.c
以及sample.o
.
但是,当我从python导入时,我收到如下所示的错误消息,并且我不明白发生了什么。下面显示了在 ipython3 中运行的错误消息。
请帮助我解决扩展模块的问题。谢谢!
In [1]: import sample
---------------------------------------------------------------------------
ImportError Traceback (most recent call last)
<ipython-input-6-a769eab12f54> in <module>()
----> 1 import sample
ImportError: dlopen(/Users/suh/pyLNKS/python-api-example/sample/sample.so, 2): Symbol not found: _gcd
Referenced from: /Users/suh/pyLNKS/python-api-example/sample/sample.so
Expected in: flat namespace
in /Users/suh/pyLNKS/python-api-example/sample/sample.so
In [2]:
以下是文件pysample.c
、sample.c
、sample.h
和setup.py
的代码。
pysample.c
1 #include <Python.h>
2 #include "sample.h"
3
4
5 static PyObject *py_gcd(PyObject *self, PyObject *args) {
6 int x, y, result;
7
8 if (!PyArg_ParseTuple(args, "ii", &x, &y)) {
9 return NULL;
10 }
11 result = gcd(x, y);
12 return Py_BuildValue("i", result);
13 }
14
15
16 /* module method table */
17 static PyMethodDef SampleMethods[] = {
18 {"gcd", py_gcd, METH_VARARGS, "Greatest commond divisor"},
19 // {"divide", py_divide, METH_VARARGS, "Integer division"},
20 {NULL, NULL, 0, NULL}
21 };
22
23 static struct PyModuleDef samplemodule = {
24 PyModuleDef_HEAD_INIT,
25 "samle", /* name of module */
26 "A sample module", /* doc string, may be NULL */
27 -1, /* size of per-interpreter state of the module,
28 or -1 if the module keeps state in global variables */
29 SampleMethods /* methods table */
30 };
31
32 PyMODINIT_FUNC
33 PyInit_sample(void){
34 return PyModule_Create(&samplemodule);
35 }
36
样本.c
1 /* sample.c */
2 #include <math.h>
3
4 /* compute the greatest common divisor */
5 int gcd(int x, int y){
6 int g = y;
7 while (x > 0){
8 g = x;
9 x = y % x;
10 y = g;
11 }
12 return g;
13 }
样本.h
1 /* sample.h */
2 #include <math.h>
3
4 extern int gcd(int x, int y);
setup.py
1 # setup.py
2 from distutils.core import setup, Extension
3
4 module1 = Extension('sample', sources = ['pysample.c'])
5
6 setup(name='simple',
7 version = '1.0',
8 description = "this is a demo package",
9 ext_modules = [module1]
10 )
11
存在一个链接问题,其中源代码 sample.c 未链接,因此 gcd 函数未定义。
因此,需要将代码 setup.py 更改为:
1 # setup.py
2 from distutils.core import setup, Extension
3
4 module1 = Extension('sample', sources = ['pysample.c','source.c'])
5
6 setup(name='simple',
7 version = '1.0',
8 description = "this is a demo package",
9 ext_modules = [module1]
10 )
11
samplemodule 结构中有一个拼写错误。模块名称是"sample",而不是"samle"