ubuntu下將c++轉換為so文件並利用python調用
python調用.so
LINUX下C++生成.so文件及編譯生成可執行文件的過程
[linux][原創]C++ so庫的編譯python調用
python 打包成 so | python 調用cpp | python 調用C++簡單例子
C++轉so文件
這里以簡單的加法為例,代碼如下,add傳入兩個int的參數,完成加法。主函數main調用add,return結果。這里需要注意的點在於,不能忘記將函數添加到extern C中。原因是python 的ctype可以調用C而無法調用c++,加上extern "C"后,會指示編譯器這部分代碼按C語言(而不是C++)的方式進行編譯。
#include
using namespace std;
extern "C"{
double add(int, int);
}
double add(int x1, int x2)
{
return x1+x2;
}
int main()
{
int a = 1;
int b =2 ;
int c;
c = add(a,b);
return c;
}
之后打開窗口,輸入以下命令,即將上述cpp文件轉換為了so文件,注意so文件的名稱必須以lib開頭。
g++ add.cpp -fpic -shared -o libadd.so
python調用so文件
import ctypes
ll = ctypes.cdll.LoadLibrary
lib = ll("./libadd.so")
input1 = 100
input2 = 220
result1 = lib.add(input1,input2)
result2 = lib.main()
print(result1,result2)
print '***finish***'
python調用.so多個C++文件轉so文件可以看到最后結果為(320,3)
如果c++中add函數的輸入為double,則python調用so文件時需要將輸入input1 input2,以及add的輸出都轉換為double的形式,代碼如下:
lib.add.restype = ctypes.c_double
result1 = lib.add(ctypes.c_double(input1),ctypes.c_double(input2))
多個C++文件轉so文件
下面將多個cpp文件轉換為so文件,下面是一個例子:
其中convert.cpp是需要調用的函數,如下,主要的兩個函數是xy2lalong和laton2xy,兩個函數的返回都是double型的數組。
#include
#include
#include "AffineModel.h"
#include "RPCGeoModel.h"
extern "C"{
double * xy2lalong(double, double, char*);
double * latlon2xy(double, double, char*);
}
double * xy2lalong(double x, double y,char* rpcpath)
{
string m_prpc=rpcpath;
//printf("%s\n",m_prpc);
CRPCGeoModel m_prpc1;
m_prpc1.InitRPCModel(m_prpc);
double *latlon =new double[2];
m_prpc1.GetLatLonByAffine(x,y, 0,latlon[0], latlon[1]); //像素坐標轉經緯度
//printf("you input %f and %f\n", latlon[0], latlon[1]);
return latlon;
}
double * latlon2xy(double lat ,double lon,char* rpcpath)
{
string m_prpc=rpcpath;
//printf("%s\n",m_prpc);
CRPCGeoModel m_prpc1;
m_prpc1.InitRPCModel(m_prpc);
double *xy =new double[2];
m_prpc1.GetXY(lat, lon, 0, xy[0], xy[1]); //經緯度轉像素坐標
return xy;
}
對於多個cpp轉程so文件,命令如下:
g++ -std=gnu++0x convert.cpp AffineModel.cpp CommonFunc.cpp RPCGeoModel.cpp -fPIC -shared -o libconvert.so
即將cpp文件名稱都輸入至終端,然后加上-fPIC -shared -o 表示生成共享庫,最后加上 libXXX.so。注意一定要加上-std=gnu++0x,否則會出現如下錯誤。
error: ‘nullptr’ was not declared in this scope
FILE *fp= nullptr;
之后用python調用,如下。由於c++中函數的輸出是一個double的數組,那么在python的調用中也需要將函數的輸出轉換為相同的類型(lib.function.restype = ctypes.POINTER(ctypes.c_double)),即double的數組。
input1 = 100.0
input2 = 100.0
lib.xy2lalong.restype = ctypes.POINTER(ctypes.c_double)
a = lib.xy2lalong(ctypes.c_double(input1),ctypes.c_double(input2), strs)
print(a[0],a[1])
input1 = 9.1949132495
input2 = 118.038103295
lib.latlon2xy.restype = ctypes.POINTER(ctypes.c_double)
b = lib.latlon2xy(ctypes.c_double(input1),ctypes.c_double(input2),strs)
print(b[0],b[1])
print '***finish***'