liunx python调用c++库(类、函数),传入传出参数

来源:互联网 发布:淘宝店铺营销策略 编辑:程序博客网 时间:2024/06/05 11:15

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

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

1.新建test类

1.1新建 test.cpp 文件

代码如下:

#include<iostream>

           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 <test.h>,再说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 <stdio.h>                     #include <dlfcn.h>   //必须有                   #include <iostream>                   #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::vector<cv::Rect> vRect, const std::string sModelPath, cv::Vec3f&pose)

 

输入参数

const cv::Mat img:图片数据

conststd::vector<cv::Rect> vRect:人脸区域

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<<img.rows<<","<<img.cols<<std::endl;           uchar* pxvec =img.ptr<uchar>(0);           for (i=0; i<rows*cols*2*3; i++)           {                    if (0==i%2)                    {                            intii = i/cols/2/3;                             pxvec =img.ptr<uchar>(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<<img.rows<<","<<img.cols<<std::endl;           uchar* pxvec =img.ptr<uchar>(0);           for (i=0; i<rows*cols*2; i++)           {                    if (0==i%2)                    {                             int ii = i/cols/2;                             pxvec =img.ptr<uchar>(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::vector<cv::Rect> vRect参数修改

c++库部分

1.      const cv::vector<cv::Rect>vRect参数改成(int* rect, int num)

2.      将int* rect人脸区域数据解析成cv::vector<cv::Rect> vRect;

代码如下:

vector<cv::Rect> show_rect(int* rect, introws){vector<cv::Rec > vRect;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<rows*cols*2; i++){          if (0==i%2)           {                   int ii = i/cols/2;                    j = i%(cols*2)/2;                    if (0==j)                    {                             x = rect [i];                    }                    else if (1==j)                    {                             y = rect [i];                    }                    else if (2==j)                    {                             w = rect [i];                    }                    else if (3==j)                    {                             h = rect [i];                             //printf("rect[%d][%d] = %d,%d,%d,%d\n", ii, j, x,y,w,h);                                                      roi = cv::Rect (x,y,w,h);//(17,42,76,75);                             vRect.push_back(roi );                    }           }}return vRect;}

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 <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc.hpp>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 cv2import ctypesimport numpy as npdll = cdll.LoadLibrary('/LandmarkDetector/class_so/demo.so');# model pathsModelPath = "/LandmarkDetector/model/main_clnf_general.txt"#image datasrc = cv2.imread("/OpenFace-master/test/face_0.jpg") #0-graycols = src.shape[1]rows = src.shape[0]#print('img shape:{}'.format(src.shape))channels = 0if 3==len(src.shape):channels = 3src = np.asarray(src, dtype=np.int) src1 = src.ctypes.data_as(ctypes.c_char_p)#fx fy cx cycx = cols / 2.0cy = rows / 2.0fx = 500 * (cols / 640.0)fy = 500 * (rows / 480.0)fx = (fx + fy) / 2.0fy = fxcx1 = c_float(cx)cy1 = c_float(cy)fx1 = c_float(fx)fy1 = c_float(fy)#head poseclass 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)



附件


 
原创粉丝点击