使用C写Python的模块

背景

之前已经写过一个rust给python做扩展包的了。然后我就在想,如何使用C给python做扩展呢,毕竟python的底层就是使用C写的。

于是整理了网上的资料,分享一个简单的demo。

环境

  1. 系统:MAC 12.3.1系统(已经安装xcode)
  2. IDE:使用的是Clion
  3. python:Anaconda安装的python 3.9版本

步骤

1. 创建项目

使用clion创建一个项目:【C可执行文件】 -> 项目名称为【untitled0430004】-> 语言标准为【C17】。
使用C写Python的模块_第1张图片

2. 修改cmake

进入项目后,clion已经创建了一个cmakeLists.txt。

cmakeLists.txt导入库,导入库后,Clion可以在我们写c的时候,会有自动代码提醒的功能。(cmake在本次项目中不起到编译作用)。

具体是在cmakeLists.txt里面再

添加下面代码:

find_package(PythonLibs REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} ${PYTHON_LIBRARIES})

添加完成后,大概是这样的(这里面的中文只是为了给你看到,实际上不建议在cmakelist里面添加中文注释)
使用C写Python的模块_第2张图片

3. 编写main.c文件

这里直接分享我写的文件代码了,把下面的代码放到main.c

#include 
#include 

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的文件中。

  1. 创建一个名字叫setup.py的文件。

  2. 文件结构如下:
    使用C写Python的模块_第3张图片

  3. 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 .即可。
使用C写Python的模块_第4张图片

最后成功编译且安装成功,打印出如下信息:
使用C写Python的模块_第5张图片

6.测试这个包

不难发现这个包的名字叫_hello

创建一个文件:code001.py

写入下面的代码,做测试:

import _hello

if __name__ == '__main__':
    print(_hello.hello_world())
    print(_hello.hello("ok"))
    print(_hello.hello("wo hao e"))

效果如下:整体来看也没什么问题。
使用C写Python的模块_第6张图片

注意事项

  1. 这里的cmake在编译的时候,好像是没起到什么作用。只是让我们写代码更加舒服了。因为clion在做代码自动补全的时候,是依靠cmakelist来的,如果cmakelist里面导入了包,那么clion就会对这个包内的所有函数做补全。
  2. 这里的案例都是很简单的,只是流程跑通了,具体细节我没有介绍(可以看参考链接),后面再做复杂的介绍。(我也在学习,请大家多多指教)。

参考链接

  1. camke导入python库,是在这里看到的:https://blog.csdn.net/fireflychh/article/details/77413005
  2. 这套代码的内容是从这里学到的:https://www.youtube.com/watch?v=HrEzCI3jIHw

阅读更多

list

你可能感兴趣的:(python,cpp,python,c语言)