python中调用C++函数
- 无参调用
- 单变量传入与返回调用
- numpy数组传入与返回调用
- c++类调用
- 用python写不香吗?还这么复杂调用C++?
一、 无参调用
在python中调用无参数和无返回的C++函数,具体的使用方式如下:
C++API函数的编写形式:
#include<iostream>
#include<string>
using namespace std;
extern "C"{
int hehe(void){
cout << "hello world!" << endl;
return 0;
}
}
将编写的.cpp文件生成.so动态链接库在ubuntu命令行中执行如下命令:
g++ -o xxx.os -shared -fPIC xxx.cpp
在相应的文件下就可看到生成的xxx.so文件。
python调用生成的动态链接库:
import ctypes
dll = ctypes.cdll.LoadLibrary('./doc.so')
dll.hehe()
运行python文件得到如下结果:
二、单变量传入与返回调用
在C++函数中需要python程序传入一个单变量的参数,整形,浮点型或者字符型。其中对应关系如下:
C++的程序如下:
#include <iostream>
#include <string>
using namespace std;
extern "C"{
int hehe(int a){
int i = 0;
i = a * a;
return i;
}
}
对用python的程序为:
import ctypes
dll = ctypes.cdll.LoadLibrary('./doc.so')
a = 23
a2 = dll.hehe(a)
print(a2)
运行结果:
三、numpy数组传入与返回调用
对于numpy数组传入C++函数与之前的但变量传入大不相同:
1、首先对numpy数组处理得到存储位置的指针(切记numpy数组内存一定要连续)
2、将得到的指针传递给对应的C++函数。
在这个过程中,会有一个问题出现,比如numpy数组为一个二维的矩阵,但C++得到参数只是一个指针,所以我们要有一个计算。将多维空间中的位置坐标转换为一维中的指针下标:举例如下:
假设有一个多维的矩阵MxNxH,转换为内存中的实际存储顺序为第一行第一列的H个元素-第一行第二列的H个元素。。。依次类推
3、对于传入指针的返回,因为传入的是实际物理地址,所以在C++函数中对数据的改变,在python对应的也会发生相应的改变。
具体C++程序为:
#include <iostream>
#include <string>
using namespace std;
extern "C"{
void hehe(int* a,int rows,int cols){
int row,col;
for(row = 0;row < rows; row++)
{
for(col = 0;col < cols;col++)
{
int ind = row * cols + col;
a[ind] = a[ind]* a[ind];
}
}
}
}
与之相对应的python文件为:
import ctypes
import numpy as np
dll = ctypes.cdll.LoadLibrary('./doc.so')
a = np.array([[1,2,3],[2,3,4],[3,4,5]],dtype=np.int32)
p = a.ctypes.data_as(ctypes.POINTER(ctypes.c_int32))
print(a)
dll.hehe(p,3,3)
print(a)
运行python文件得到的结果为:
四、numpy数组传入与返回调用
class test{
public:
void test(void);
};
extern "C"{
test t;
void test(void)
{
t.test();
}
}
void test::test(void)
{
cout << "hello world!" << endl;
}
用python写不香吗?还这么复杂调用C++?
别的方面具体不不清楚两者的区别,但是就从处理速度来说,我做了一个小实验,相信看完之后就没有类似的疑问了。实验的内容为:对于一个512x512x10全一矩阵执行所有元素加1操作,分别用python和C++来执行,看需要的时间。
具体的代码:
#include<iostream>
#include<string>
using namespace std;
extern "C"{
void hehe(int* p ,int row,int col,int channel){
int h,w,c;
for(h = 0;h < row;h++)
{
for(w = 0;w < col;w++)
{
for(c = 0;c < channel;c++)
{
int ind = h*(col * channel) + w * channel + c;
p[ind] = p[ind] + 1;
}
}
}
}
}#include<iostream>
#include<string>
using namespace std;
extern "C"{
void hehe(int* p ,int row,int col,int channel){
int h,w,c;
for(h = 0;h < row;h++)
{
for(w = 0;w < col;w++)
{
for(c = 0;c < channel;c++)
{
int ind = h*(col * channel) + w * channel + c;
p[ind] = p[ind] + 1;
}
}
}
}
}
import ctypes as ct
import numpy as np
import time
def add1(m,h,w,c):
for row in range(h):
for col in range(w):
for channel in range(c):
m[row][col][channel] += 1
ll = ct.cdll.LoadLibrary("./test.so")
m = np.ones([10,512,512],np.int32)
print(m.shape)
h,w,c = m.shape[:3]
p = m.ctypes.data_as(ct.POINTER(ct.c_int32))
t1 = time.time()
ll.hehe(p,h,w,c)
print('c++ time:',time.time()-t1)
t2 = time.time()
add1(m,h,w,c)
print('python time:',time.time()-t2)
运行结果(睁大眼睛看清楚哟):