背景
之前已经写过一个rust给python做扩展包的了。然后我就在想,如何使用C给python做扩展呢,毕竟python的底层就是使用C写的。
于是整理了网上的资料,分享一个简单的demo。
环境
- 系统:MAC 12.3.1系统(已经安装xcode)
- IDE:使用的是Clion
- python:Anaconda安装的python 3.9版本
步骤
1. 创建项目
使用clion创建一个项目:【C可执行文件】 -> 项目名称为【untitled0430004】-> 语言标准为【C17】。
2. 修改cmake
进入项目后,clion已经创建了一个cmakeLists.txt。
在cmakeLists.txt
导入<Python.h>
库,导入<Python.h>
库后,Clion可以在我们写c的时候,会有自动代码提醒的功能。(cmake在本次项目中不起到编译作用)。
具体是在cmakeLists.txt
里面再
添加下面代码:
find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${PYTHON_LIBRARIES})
添加完成后,大概是这样的(这里面的中文只是为了给你看到,实际上不建议在cmakelist里面添加中文注释)
3. 编写main.c
文件
这里直接分享我写的文件代码了,把下面的代码放到main.c
。
#include <stdio.h>
#include <Python.h>
static PyObject *_hello_wrold(PyObject *self) {
return PyUnicode_FromString("hello world 1");
}
static PyObject *_hello(PyObject *self, PyObject *args) {
PyObject *name;
if (!PyArg_ParseTuple(args, "U", &name)) {
return NULL;
}
PyObject *upper = PyObject_CallMethod(name, "upper", NULL);
if (!upper) {
return NULL;
}
PyObject *ret = PyUnicode_FromFormat("hello %U", upper);
return ret;
}
static struct PyMethodDef methods[] = {
{"hello_world", (PyCFunction) _hello_wrold, METH_NOARGS},
{"hello", (PyCFunction) _hello, METH_VARARGS},
{NULL, NULL}
};
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"_hello",
NULL,
-1,
methods
};
PyMODINIT_FUNC PyInit__hello(void) {
return PyModule_Create(&module);
}
int main() {
// printf("Hello, World!\n");
return 0;
}
4. 打包这个包
python给文件打包,都是使用的setuptools
包(python的包),需要把打包的东西,放在一个名字叫setup.py
的文件中。
-
创建一个名字叫
setup.py
的文件。 -
文件结构如下:
-
向
setup.py
里面写入python代码,内容如下:
from setuptools import setup
from setuptools import Extension
setup(
name="hello-lib",
version="0.0.1",
ext_modules=[Extension("_hello", ['main.c'])]
)
5. 安装这个包
在这个项目下,打开终端, 输入pip install .
即可。
最后成功编译且安装成功,打印出如下信息:
6.测试这个包
不难发现这个包的名字叫_hello
。
创建一个文件:code001.py
写入下面的代码,做测试:
import _hello
if __name__ == '__main__':
print(_hello.hello_world())
print(_hello.hello("ok"))
print(_hello.hello("wo hao e"))
效果如下:整体来看也没什么问题。
注意事项
- 这里的cmake在编译的时候,好像是没起到什么作用。只是让我们写代码更加舒服了。因为clion在做代码自动补全的时候,是依靠cmakelist来的,如果cmakelist里面导入了包,那么clion就会对这个包内的所有函数做补全。
- 这里的案例都是很简单的,只是流程跑通了,具体细节我没有介绍(可以看参考链接),后面再做复杂的介绍。(我也在学习,请大家多多指教)。
参考链接
- camke导入python库,是在这里看到的:https://blog.csdn.net/fireflychh/article/details/77413005
- 这套代码的内容是从这里学到的:https://www.youtube.com/watch?v=HrEzCI3jIHw
阅读更多
list