linux 动态库 传递vector,liunx python调用c++库(类、函数),传入传出参数

一、使用c++封装动态库

参考文献:http://www.linuxidc.com/Linux/2012-09/70502.htm

1.新建test类

1.1新建 test.cpp 文件

代码如下:

#include

extern "C"

int myadd(int a, int  b)

{

return a + b;

}

备注:extern"C" 必须有,不然会报undefined symbol: myadd.

1.2新建test.h文件

代码如下:

#ifndef _TESTSO_H

#define_TESTSO_H

extern"C"

{

intmyadd(int a, int b);

typedefint myadd_t(int, int); // myadd function type

}

#endif// _TESTSO_H

备注:test.h文件可以没有,因为test.cpp也没有#include ,再说myadd()函数也不是类的成员函数。

2.编译

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

备注1:

-fPIC:生成位置无关目标代码,适用于动态连接;

-L path:表示在path目录中搜索库文件,如-L.表示在当前目录;

-I path:表示在path目录中搜索头文件;

-o file:制定输出文件为file;

-shared:生成一个共享库文件;

备注2:

编译多个cpp文件:

g++ -shared-fPIC -o demo.so demo.cpp CCNF_patch_expert.cpp LandmarkDetectorFunc.cppLandmarkDetectorModel.cpp LandmarkDetectorUtils.cppLandmarkDetectorParameters.cpp LandmarkDetectionValidator.cpp Patch_experts.cppPAW.cpp PDM.cpp SVR_patch_expert.cpp stdafx.cpp$(pkg-config opencv --cflags --libs) $(/usr/lib/x86_64-linux-gnu/libboost_filesystem.so;/usr/lib/x86_64-linux-gnu/libboost_system.so)-I /usr/include/boost -L /usr/lib/x86_64-linux-gnu/ -I boost_system –l boost_filesystem

(在使用上面命令代码编译时,先将代码放到txt中,写成一行,最后在赋值到命令行进行编译,不然可能会出错)

,最好是写个makefile文件来编译。

3. C++方式调用库

3.1新建main.cpp

代码如下:

#include #include //必须有

#include #include"test.h" // for dynamic library函数

int main(int argc, char*argv[])

{

if (2 != argc)

{

return-1;

}

const char *soname =argv[1];

void *so_handle = dlopen(soname,RTLD_LAZY); // 载入.so文件

if (!so_handle)

{

fprintf(stderr,"Error: load so `%s' failed./n", soname);

return-1;

}

dlerror(); // 清空错误信息

myadd_t *fn =(myadd_t*)dlsym(so_handle,"myadd"); // 载入函数

char *err =dlerror();

if (NULL != err)

{

fprintf(stderr,"%s/n", err);

return-1;

}

printf("myadd57 + 3 = %d/n", fn(57, 3)); // 调用函数

dlclose(so_handle);// 关闭so句柄

return 0;

}

3.2 编译

g++ main.cpp -o main -ldl

备注:如果没有-ldl参数,会报undefinedreference to `dlopen'错误解决。

3.3运行

./main test.so

4. Python方式调用库

4.1新建main.py

from ctypesimport *

#loaddll and get the function object

dll= cdll.LoadLibrary(’/landmark/LandmarkDetector/test.so');

t= dll.myadd(1,2)

print(t)

4.2运行

python main.py

二、python调c++库,并传入传出参数

2.1 c++库函数

例如:

c++库函数:

inttest(const cv::Mat img,  conststd::vectorvRect, const std::string sModelPath, cv::Vec3f&pose)

输入参数:

const cv::Mat img:图片数据

conststd::vectorvRect:人脸区域

const std::stringsModelPath:模型路径

输出参数:

cv::Vec3f& pose:人脸角度(x,y,z)

由于python、c++是两种不同的编程语言,在相互调用时,需要将数据类型转换成对方认可的。

2.2 输入参数

2.2.1 const cv::Mat img参数修改

参考文献:http://bbs.csdn.net/topics/340060802

C++库部分

1.      const cv::Mat img 参数改成(int*img, int rows, int cols, int channels)

2.      将int* img图像数据解析成cv::Mat img。

代码如下:

cv::Mat show_matrix(int *matrix, int rows, int cols, int channels)

{

int i, j, c;

if (3==channels)

{

cv::Mat img(rows,cols,CV_8UC3,cv::Scalar(0,0,0));

std::cout

for (i=0; i(ii);

j = i%(cols*2*3)/2;

c = j%3;

j = j/3;

pxvec[j*3 + c] =(unsigned char)matrix[i];

//printf("pxvec[%d][%d][%d]= %d\n", ii,j,c, matrix[i]);

}

}

return img;

}

else

{

cv::Mat img(rows,cols,CV_8UC1,cv::Scalar(0,0,0));

std::cout

for (i=0; i(ii);

j = i%(cols*2)/2;

pxvec[j] =(unsigned char)matrix[i];

//printf("pxvec[%d][%d]= %d\n", ii, j, matrix[i]);

}

}

return img;

}

}

Python调用部分

代码如下:

src= cv2.imread("/OpenFace-master/test/face_0.jpg") #0 - gray

cols= src.shape[1]

rows =src.shape[0]

channels= 0

if 3==len(src.shape):

channels= 3

src= np.asarray(src, dtype=np.int)#需要与定义的int* img类型一致

src1 = src.ctypes.data_as(ctypes.c_char_p)#将一个多维数组转成char*

t =dll.test(src1, rows, cols, channels)

备注:

src = np.array([[11,22],[3,4]])

src1 = src.ctypes.data_as(ctypes.c_char_p)

t = dll.test(src1, rows, cols, channels)

c++中src1的数值如下:

matrix[0] = 11

matrix[1] = 0

matrix[2]= 22

matrix[3]= 0

matrix[4]= 3

matrix[5]= 0

matrix[6]= 4

matrix[7] = 0

2.2.2  const cv::vectorvRect参数修改

c++库部分

1.      const cv::vectorvRect参数改成(int* rect, int num)

2.      将int* rect人脸区域数据解析成cv::vectorvRect;

代码如下:

vectorshow_rect(int* rect, introws)

{

vectorvRect;

int cols = 4; //(x,y,w,h)

int i,j;

int x=0,y=0,w=0,h=0;

cv::Rect roi;

for (i=0; i

Python调用部分

代码如下:

num = 1  #表示人脸区域的个数

rect = np.zeros((num,4),dtype=np.int) #4表示人脸区域的(x,y,w,h)

rect[0][0] = 0

rect[0][1] = 0

rect[0][2] = cols-1

rect[0][3] = rows-1

#print (src.dtype) #uint8

rect = np.asarray(rect, dtype=np.int)

#print (src.dtype)#int64

rect1 = rect.ctypes.data_as(ctypes.c_char_p)

t = dll.test(src1, rows, cols, channels, rect1, num)

备注:如果是float类型,需要使用 c_float(cx)转换后,再传入就ok,不然会报类型不匹配。

2.3  输出参数

参考文献:http://blog.csdn.net/uniqsa/article/details/78603082

2.3.1  cv::Vec3f& pose参数修改

c++库部分

1.      将cv::Vec3f& pose参数改成struHeadPose& pose;

2.      在test.cpp中定义struHeadPose结构体:

structstruHeadPose

{

float                            angleX;

float                            angleY;

float                            angleZ;

};

3.      struHeadPose pose赋值并返回:

pose.angleX = angleX;

pose.angleY = angleY;

pose.angleZ= angleZ;

python调用部分

代码如下:

class struHeadPose(ctypes.Structure):

_fields_ =[("angleX", ctypes.c_float),("angleY",ctypes.c_float),("angleZ", ctypes.c_float)]

pose =struHeadPose(0.0, 0.0, 0.0)

sModelPath ="/LandmarkDetector/model/main_clnf_general.txt"

t = dll.test(src1,rows, cols, channels, rect1, num, sModelPath, ctypes.byref(pose))

print(pose.angleX)

print(pose.angleY)

print(pose.angleZ)

三、c++封装类的动态库、python调用

参考文献:http://blog.csdn.net/wuchuanpingstone/article/details/77763455(很不错的)

3.1 c++封装类的动态库

3.1.1 demo.h文件

#ifndef _DEMOSO_H

#define _DEMOSO_H

// OpenCV includes

#include #include #include struct struHeadPose

{

float angleX;

float angleY;

float angleZ;

};

class CCaculateFaceAngle

{

public:

int getPose(int* imgData, int h, int w, int channels, float cx, float cy, float fx, float fy,struHeadPose& pose);

int LoadModel(char* sModelPath);

private:

LandmarkDetector::FaceModelParameters m_det_parameters;

LandmarkDetector::CLNF m_clnf_model;

};

#endif // _DEMOSO_H

3.1.2 demo.cpp文件

#include "demo.h"

int CCaculateFaceAngle::getPose(int* imgData, int h, int w, int channels, float cx, float cy, float fx, float fy, struHeadPose& pose)

{

内容省略

}

int CCaculateFaceAngle::LoadModel(char* sModelPath)

{

内容省略

}

//以下是重点,不然不会导出c++的类。

extern "C"

{

CCaculateFaceAngle obj;

int getPose(int* imgData, int h, int w, int channels, float cx, float cy, float fx, float fy,struHeadPose& pose)

{

return obj.getPose(imgData, h, w, channels, cx, cy, fx, fy,pose);

}

int LoadModel(char* sModelPath)

{

return obj.LoadModel(sModelPath);

}

}

3.2 python调用c++类

from ctypes import *

import cv2

import ctypes

import numpy as np

dll = cdll.LoadLibrary('/LandmarkDetector/class_so/demo.so');

# model path

sModelPath = "/LandmarkDetector/model/main_clnf_general.txt"

#image data

src = cv2.imread("/OpenFace-master/test/face_0.jpg") #0-gray

cols = src.shape[1]

rows = src.shape[0]

#print('img shape:{}'.format(src.shape))

channels = 0

if 3==len(src.shape):

channels = 3

src = np.asarray(src, dtype=np.int)

src1 = src.ctypes.data_as(ctypes.c_char_p)

#fx fy cx cy

cx = cols / 2.0

cy = rows / 2.0

fx = 500 * (cols / 640.0)

fy = 500 * (rows / 480.0)

fx = (fx + fy) / 2.0

fy = fx

cx1 = c_float(cx)

cy1 = c_float(cy)

fx1 = c_float(fx)

fy1 = c_float(fy)

#head pose

class struHeadPose(ctypes.Structure):

_fields_ = [("angleX", ctypes.c_float),("angleY", ctypes.c_float),("angleZ", ctypes.c_float)]

pose = struHeadPose(0.0, 0.0, 0.0)

if dll.LoadModel(sModelPath) > -1:

t = dll.getPose(src1, rows, cols, channels, cx1, cy1, fx1, fy1, ctypes.byref(pose))

print (pose.angleX)

print (pose.angleY)

print (pose.angleZ)

附件

7624fbc8439e666fdac507d775e8e9f3.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值