{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Python 与 C++ 语言\n", "C++ 语言是对 C 语言的扩展,两者常被视为一个整体,集成于同一编译环境之中——你只须将一个 C 程序的文件后缀由 .c 改为 .cpp,它就成了 C++ 程序。C++ 在 C 语法之上增加了许多高级特性,运行效率相近而更加灵活多变,因此其应用领域也更为广阔。\n", "![Cpp.png](https://upload-images.jianshu.io/upload_images/10829283-d4429d8ec4124538.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n", "\n", "下面来看一个 C++ 程序示例 myclass.cpp——这段源码首先包含了 C++ 标准库的“输入输出流”头文件,能够更方便地读入数据并打印结果(可以对照之前 C 代码的输入输出方式);随后定义了一个“圆”类,用一个私有成员变量表示半径,并用两个公有成员函数分别计算面积和周长(可以对照 Python 中定义类及创建实例的语法):\n", "```\n", "#include \n", "const double PI = 3.14159;\n", "class Circle\n", "{\n", " private:\n", " double r;\n", " public:\n", " Circle(double r_)\n", " {\n", " r = r_;\n", " }\n", " double area()\n", " {\n", " return PI * r * r;\n", " }\n", " double perimiter()\n", " {\n", " return 2 * PI * r;\n", " }\n", "};\n", "int main()\n", "{\n", " double r;\n", " std::cout << \"请输入圆的半径:\";\n", " std::cin >> r;\n", " Circle c = Circle(r);\n", " std::cout << \"圆的面积为:\" << c.area() << std::endl;\n", " std::cout << \"圆的周长为:\" << c.perimiter() << std::endl;\n", "}\n", "```\n", "\n", "你已经知道 Python 能够使用 C/C++ 共享库,实际上 C/C++ 还可以编写 Python 专用共享库也就是扩展模块——让我们来尝试一下,首先新建文件 mymath.cpp:\n", "```\n", "/* C/C++编写Python扩展模块示例\n", "需要包含Python提供的头文件,例如VSCode应添加以下配置\n", "\"C_Cpp.default.includePath\": [\"~/miniconda3/include/python3.7m\"],\n", "*/\n", "#include \n", "/* 计算斐波纳契数列的项 */\n", "int cFib(int n)\n", "{\n", " if (n < 2)\n", " return n;\n", " return cFib(n - 1) + cFib(n - 2);\n", "}\n", "/* Python函数 */\n", "static PyObject *fib(PyObject *self, PyObject *args)\n", "{\n", " int n;\n", " if (!PyArg_ParseTuple(args, \"i\", &n))\n", " return NULL;\n", " return Py_BuildValue(\"i\", cFib(n));\n", "}\n", "/* Python方法列表 */\n", "static PyMethodDef module_methods[] = {\n", " {\"fib\", fib, METH_VARARGS, \"calculates the fibonachi number\"},\n", " {NULL, NULL, 0, NULL}};\n", "/* Python模块 */\n", "static struct PyModuleDef mymath =\n", " {\n", " PyModuleDef_HEAD_INIT,\n", " \"mymath\", /* 模块名 */\n", " \"mymath module\", /* 模块文档字符串 */\n", " -1, /* 保持全局状态 */\n", " module_methods};\n", "/* Python模块初始化 */\n", "PyMODINIT_FUNC PyInit_mymath()\n", "{\n", " return PyModule_Create(&mymath);\n", "}\n", "```\n", "\n", "以上源码其实只用了 C 语法。第一行指令是包含官方 Python/C API 的头文件;第一个函数 cFib 实现具体功能——递归地计算斐波那契数列的项:第一项为 0,第二项为 1,之后每一项都是其前面两项的和;其余函数都是按照规范来定义模块的信息。接下来新建文件 setup.py:\n", "```\n", "from distutils.core import setup, Extension\n", "mymath = Extension('mymath', sources=['mymath.cpp'])\n", "setup(ext_modules=[mymath])\n", "```\n", "\n", "输入以下命令即可调用编译器在当前目录下生成扩展模块文件,注意:在 Windows 下需要 Visual C++ Build Tools http://go.microsoft.com/fwlink/?LinkId=691126\n", "```\n", "python setup.py build_ext --inplace # 执行时会提示实际调用的编译命令\n", "```\n", "\n", "最后在交互模式下测试:\n", "```\n", "In [1]: import mymath\n", "\n", "In [2]: mymath.fib?\n", "Docstring: calculates the fibonachi number\n", "Type: builtin_function_or_method\n", "\n", "In [3]: [mymath.fib(i) for i in range(10)]\n", "Out[3]: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]\n", "```\n", "\n", "说起交互模式,其实 C/C++ 也可以有交互模式,而且还支持我们刚接触过的 Jupyter,如果需要就请安装 Cling https://github.com/root-project/cling\n", "![Cpp_Jupyter.png](https://upload-images.jianshu.io/upload_images/10829283-93bfa274f9a35552.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3.7", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }