1 摘要
大家都知道Python的优点是开发效率高,使用方便;C++则是运行效率高,这两者可以相辅相成。在Python中调用C/C++代码有两种方式,这里就说其中更简单的一种。
- 将C/C++代码编译成动态链接库
- 在Python中通过ctypes.cdll.LoadLibrary()直接加载该动态链接库,调用其中的函数。
2 在Python中加载c/c++动态链接库
- 编写C/C++程序
factorial.c
int factorial(int n){
if (n < 0){
return -1;
}
if (n == 0){
return 1;
}
return n * factorial(n-1);
}
- 编译生成动态链接库文件
$ gcc -o factorial.so -shared -fPIC factorial.c
- 在Python中调用
from ctypes import *
basic = cdll.LoadLibrary('/Users/wisdom/program/basic/factorial.so')
basic.factorial(5)
在macOS中,须给出动态链接库文件的绝对路径,在Linux中只需给出相对路径。
3 Python与C/C++程序间传递图像
-
编写C++程序
showimage.cpp
#include "showimage.h"
using namespace cv;
extern "C"
{
/*
* Abstract: Convert data to image and show it
* Parameters: width, height: width and height of image
* data: Pointer of the image data
*/
void show(int width, int height, uchar* data)
{
Mat image(height, width, CV_8UC3);
uchar * pimage;
int index = 0;
for (int row = 0; row < height; row++)
{
// Assign row pointer
pimage = image.ptr<uchar>(row);
for (int col = 0; col < width; col++)
{
for (int channel = 0; channel < 3; channel++)
{
// Assign data to image
pimage[3*col+channel] = data[index++];
}
}
}
imshow("Image", image);
waitKey(0);
}
}
-
编写C++程序头文件
showimage.h
#include <opencv2/opencv.hpp>
extern "C"
{
void show(int width, int height, uchar* data);
}
- 编译生成动态链接库
$ gcc -o image.so -shared -fPIC showimage.cpp -lopencv_core -lopencv_highgui
-fPIC:生成位置无关目标代码,适用于动态连接;
-L path:表示在path目录中搜索库文件,如-L.表示在当前目录;
-I path:表示在path目录中搜索头文件;
-o file:制定输出文件为file;
-shared:生成一个共享库文件;
- 编写Python程序
import cv2
import ctypes
from ctypes import cdll
import numpy as np
# Read image
image = cv2.imread('test.jpg')
image_data = np.asarray(image, dtype=np.uint8)
# Convert data to one dimension char array of C language and get the pointer of the array
image_data = image_data.ctypes.data_as(ctypes.c_char_p)
# Load C/C++ dynamic library
image_fun = cdll.LoadLibrary("./image.so")
# Show image by C++ function
image_fun.show(image.shape[1], image.shape[0], image_data)
- 执行Python程序
$ python3 showimage.py
-
执行后,Python程序会读入图像,将其转换成C类型的字符数组
-
然后加载C语言动态链接库,将字符数组的指针及图像宽、高传给C语言的show()函数。
-
show()函数会将传入的字符数组转换成图像,并显示出来。