事实证明,用Python有时确实不如C语言来的快,现在考虑将两者混编的问题。参考网上的东西,做点笔记:
1.How to Call a C Function in Python
(1)Using the ctypes Library
Python ctypes库是一个强大的资源,它使我们能够生成与C兼容的数据类型,并使用Python直接调用动态链接库或共享库中的函数。下面,你将找到一个全面的演练,详细介绍如何利用ctypes调用C函数:
步骤一:引入库
import ctypes
步骤二:加载包括C函数的共享库
lib = ctypes.CDLL('./mylibrary.so')
这一步将共享库文件加载到存储器中,使得其中的函数能够被访问
步骤三:声明函数原型
my_function = lib.my_function
my_function.argtypes = [ctypes.c_int, ctypes.c_int]
my_function.restype = ctypes.c_int
在这一步,通过将库中的C函数和Python变量联系起来,我们建立了函数原型。而且,我们使用argtypes定义参数类型和使用restype定义返回类型。
步骤四:从Python调用C函数
result = my_function(5, 10)
print(result)
最后,我们就像调用其他任何Python函数一样调用C函数。传入所需的参数,它将执行相应的C代码。执行结果将被存储在变量中。
那么问题来了,如果我在Windows中实施混编,该怎么建立C语言的动态连接库或共享库?
读读这个吧:How to Create C/C++ Dynamic-link Libraries in Windows
将程序模块化为单独的组件,以简化部署和安装
根据微软官方,dll文件是:
包含代码和数据的库,这些代码和数据可以同时被多个程序使用。这有助于促进代码重用和有效的内存使用。
通过使用dll,一个程序可以被模块化成独立的组件,每一个模块可以在运行时间被加载到主程序中,如果那个模块被安装了。因为模块是分开的,所以程序的加载时间更快,并且只有在请求该功能时才加载模块。
在Windows平台上,共享库被称为动态链接库(.dll)。而在其他平台中则被表示为.so扩展的共享对象。
1.在根目录上开3个头文件
(1)include —— 为了存储头文件。在如何与编译的共享库交互的问题上,头文件将被用于应用。如果其他开发者希望使用你的共享库去开发他们自己的程序,头文件就是必不可少的。
(2)obj —— 为了在编译期间存储所创造的临时obj文件,你可以安全的删掉这些文件。
(3)src —— 为了存储你的功能的必备代码。在部署期间,你将从包中排除这些文件。对使用你的程序的用户只提供共享库和可执行文件。
2.写头文件add.h
这个头文件要写在上述文件夹中的include文件夹,内容为:
#ifndef _ADD_H
#define _ADD_H
extern "C"
{
__declspec(dllexport) int add(int, int);
__declspec(dllexport) int sub(int, int);
__declspec(dllexport) int mul(int, int);
}
#endif
如果用C来写,就不需要extern和delspec(dllexport)
3.执行代码
现在转移到src文件夹创造新文件add.cpp:
#include "add.h"
extern "C"
{
__declspec(dllexport) int add(int a, int b)
{
return a + b;
}
__declspec(dllexport) int sub(int a, int b)
{
return a - b;
}
__declspec(dllexport) int mul(int a, int b)
{
return a * b;
}
}
4.返回根目录创造主文件main.cpp:
#include <iostream>
#include "add.h"
int main()
{
std::cout << add(2, 2) << "|" << sub(3, 1) << "|" << mul(3, 3) << std::endl;
return 0;
}
5.对象文件:
Visual Studio向我们提供了他们自己的开发者命令提示符,这允许我们编译可执行文件。我们能在Visual Studio的目录上找到Native Tools Command Prompt for VS。比如这样:
现在要让它指向之前的main.cpp所在的目录,刚刚发现转移目录转不动,参考这篇就好了Change directory in visual studio command prompt。其实就是cd /d 后面带上去的目录就行。
输入命令:
cl /EHsc /c .\src\*.cpp /I .\include /Fo".\obj\\"
执行结果:
这条命令中有几个符号要注意:
(1) /c —— 源代码文件的位置,使用*去包含所有在src文件夹中的cpp文件。
(2) /I —— 头文件的位置,默认将包含.h扩展的文件。
(3) /Fo —— 将要在编译期间被创造的临时obj文件的位置,请注意在/Fo的后面不要留空。
现在你就会发现,在文件夹obj里多了一个叫add.obj的文件。
6.链接.obj文件并创建一个共享库
运行下面的命令
link /DLL /OUT:add.dll .\obj\*.obj
之后多出了这3个文件
(1)add.dll —— 你的程序的共享库,你的可执行文件需要它来运行相关的函数。
(2)add.exp —— 这个文件是可以安全的删除的。
(3)add.lib —— 编译期间所需的静态库,用来制作可执行文件
7.可执行文件
最后就是创造可执行文件了,运行下面的指令:
cl /EHsc main.cpp /Fetest.exe /I .\include /link *.lib
我们将使用.lib文件而不是.dll文件,因为编译需要静态库,而动态链接库用于编译后运行可执行文件。运行结果:
在根文件夹中,有可直接运行的文件test.exe.
您可以简单地部署以下文件以供使用。确保test.exe和add.dll两者位于同一目录中。
注意: 博文How to Create C/C++ Dynamic-link Libraries in Windows所描述的方法可能只适合写成C++的情况。