MakeFile.Python & C++ Programe Toturial
MakeFile.Python & C++ 混编教程 上
对于习惯IDE的Programmer来说 底层实际上是非常陌生的领域 然而下探到C++编译机制,对于一个合格的工程师又是非常有必要掌握的技术因此 本篇文章将讲解利用MakeFile 来实现Python C++混编的目的
首先不同平台的编译,存在着显著的差别:
Linux/UnixLike平台的动态链接库一般为.so为结尾(shared object)
Windows平台的动态链接库一般为.dll为结尾(Dynamic Link Library )
Linux Part:
编译器
在Linux中 主流编译器为Clang以及GNU(GCC,G++)
GCC中支持的语言常用的有
C、C++、Java、Object-C
结构类似于一个标准Unix编译器
而Clang是支持C++,CObject-C,Object-C++语言的编译器前端
其底层采用了LLVM底层虚拟机,在编译Object-C时对比GCC快三倍
总体上:
- GCC特性:
除支持C/C++/ Objective-C/Objective-C++语言外,还是支持Java/Ada/Fortran/Go等;当前的Clang的C++支持落后于GCC;支持更多平台;更流行,广泛使用,支持完备。
- Clang特性:
编译速度快;内存占用小;兼容GCC;设计清晰简单、容易理解,易于扩展增强;基于库的模块化设计,易于IDE集成;出错提示更友好
我们先以GCC为例讲解以下一个典型的C++编译指令是如何工作的
一个典型的Unix like平台的 C++程序编译要经过哪些步骤?
(更详细的解释参照C++编译过程 ,不再赘述)
而一个 gcc –h显示的帮助信息最常用的部分如下:
1 | -B <directory> Add <directory> to the compiler's search paths |
我们来尝试编译一个helloworld
main.cpp
1 |
|
对于这样一个非常基础的没有额外依赖的cpp文件来说,编译过程当然也相当简单。
1 | g++ -c main.cpp |
如果我们还想执行这个代码就要生成可执行文件
1 | g++ -o main.out main.o |
则./xx.out 就可以运行编译完成的可执行文件了
但是这个并不是典型的应用场景 我们用下面的三个代码来模拟日常更常用的C++工作模式
head.h
1 |
|
function.cpp
1 |
|
main.cpp
1 |
|
这一小段程序包含了非常多的技巧
首先定义了head以及function本地头文件和实现,在cpp文件中实现了
两个公开的方法
在main中又调用了实例化对象中的该方法
由于涉及了多个文件因此我们必须有一种方法来指定编译器的行为——MakeFile
1 | build : main.o function.o |
其中整个的格式为:
1 | target ... : prerequisites ... |
target为目标文件
prerequisites为生成目标文件所需的文件
command为编译该目标文件所需的指令
所以目前我们可以按照之前的C++编译流程图 整理出的依赖顺序为:
1.编译function.cpp依赖于head.h 生成function.o 即:
1 | function.o : head.h function.cpp |
2.编译main.cpp依赖于head.h 生成 main.o 即:
1 | main.o : main.cpp head.h |
3.编译可执行文件依赖于main.o function.o 生成指定的可执行文件(build)即:
1 | build : main.o function.o |
具体在执行过程中则遵循依赖,书写则从可执行文件开始(如果确实要生成可执行文件的话)
至此命令行中输入
1 | make |
就可以进行编译啦
1 | #结果如同 |
生成了build可执行文件
结果:
1 | c++ is best language |
通过这一步我们解决了C++编译的问题,那我们怎么解决Python和C++的混编呢?
重新编写
function.cpp
1 |
|
通常来说,在模块的头文件中对本模块提供给其他模块引用的函数和全局变量以关键字extern声明。
Tips:
extern是C/C++语言中表明函数和全局变量的作用范围的关键字,该关键字告诉编译器,其申明的函数和变量可以在本模块或其他模块中使用。
被extern “C”修饰的变量和函数是按照C语言方式进行编译和链接的
extern int a; 仅仅是一个变量的声明,其并不是在定义变量a,并未为a分配空间。变量a在所有模块中作为一种全局变量只能被定义一次,否则会出错。
extern对应的关键字是static,static表明变量或者函数只能在本模块中使用,因此,被static修饰的变量或者函数不可能被extern C修饰。
这一步的目的是通过MakeFile生成动态链接库,在Unix like系统中一般为.so文件:
1 | build : main.o function.o |
通过
1 | make pylib |
就可以生成pylib.so文件
此时我们开始建立python脚本
main.py
1 | import ctypes |
输出:
1 | Python is best language |
至此 我们完成了Python调用C++的实践
- Title: MakeFile.Python & C++ Programe Toturial
- Author: Tom Winshare
- Created at: 2023-04-21 02:23:17
- Updated at: 2023-04-21 02:26:00
- Link: https://winshare.tech/2023/04/21/CPP_Python Code Inference/
- License: This work is licensed under CC BY-NC-SA 4.0.