您的位置:首页 > 编程语言 > C语言/C++

python调用C/C++

2022-04-28 15:50 2879 查看

现在开源库中经常见到python和C/C++混用的情况,现在研究一下

python调用C/C++程序主要可以分为3步:

  • 编写C/C++实现程序。
  • 将C/C++程序编译成动态库
  • 在Python中调用编译生成的库。

python在调用C/C++程序时有一些不同,需要注意。

##原生态实现 ###python调用C

将C语言程序编译好,再使用python中的ctypes模块调用即可。

####编写C源文件

//test.c
#include<stdio.h>
int foo(int a, int b){
printf("a:%d, b:%d\n", a, b);
return 0;
}

####编译C源文件

//先生成test.o文件;然后编译为动态库test.so
gcc -o test.so -shared -fPIC test.c

生成test.so动态库文件,之后就可以在Python中调用foo函数。

这里是生成的动态库: 静态库:libxxx.a 在程序编译的时候,将库编译进可执行程序中, 运行的时候不需要外部函数库 动态库:libxxx.so 在程序运行的时候,将库加载到程序中,运行的时候需要外部函数库

####python调用编译的库

import ctypes
dll = ctypes.cdll.LoadLibrary
lib = dll('./test.so') //刚刚生成的库文件的路径
lib.foo(1, 3)

输出:

###python调用C++

由于C支持函数重载,用g编译C时编译器会给函数的名称附加上额外的信息,这样ctypes模块就会找不到g编译生成的函数。因此,要让g++按照C语言的方式编译才可以找到生成的函数名。让编译器以C语言的方式编译就要在代码中使用extern关键字将代码包裹起来。

####编写c++源程序

//test.cpp
#include <iostream>
using namespace std;

class TestLib
{
public:
void display();
void display(int a);
};
void TestLib::display() {
cout<<"First display"<<endl;
}

void TestLib::display(int a) {
cout<<"Second display:"<<a<<endl;
}
extern "C" {
TestLib obj;
void display() {
obj.display();
}
void display_int(int a) {
obj.display(a);
}
}

####编译c++源程序

g++ -o test.so -shared -fPIC test.cpp

编译参数说明:

  • -fPIC:生成位置无关目标代码,适用于动态连接;
  • -L path:表示在path目录中搜索库文件,如-L.表示在当前目录;
  • -I path:表示在path目录中搜索头文件;
  • -o file:制定输出文件为file;
  • -shared:生成一个共享库文件;

####python调用编译库

import ctypes
dll = ctypes.cdll.LoadLibrary
lib = dll('../C++/test.so')
lib.display()
lib.display_int(0)

输出:

##使用boost实现 首先boost是一个C++第三方开源库,参考:C++:Boost库。这里使用的是其中的跨语言混合编程功能

###编写C++源程序

#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
using namespace boost::python;

int Add(const int x, const int y)
{
return x + y;
}

int Del(const int x, const int y)
{
return x - y;
}

BOOST_PYTHON_MODULE(test2)
{
def("Add", Add);
def("Del", Del);
}

###编译C++源程序

g++ test.cpp -fPIC -shared -o test.so -I/usr/bin/python2.7 -I/usr/local/include -L/usr/local/lib -lboost_python

编译时需要指定boost头文件和库的路径,我这里分别是/usr/local/include和/usr/local/lib

(1)报错1 办法:

export CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/Library/Developer/CommandLineTools/SDKs/MacOSX11.3.sdk/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7

(2)报错2 还未解决

###python引入链接库

>>> import test2
>>> test2.Add(1,2)
3
>>> test2.Del(1,2)
-1

##参考 1、简单的Python调用C++程序 2、c语言将程序写为动态库,C语言函数篇(五)静态库和动态库的创建和使用 3、Python调用C++程序的几种方法

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: