Python调用c++的动态dll中数据映射(Mat类型传递及结构体传递)

参考

参考1:python调用dll数据映射
参考2:Mat,uchar*,uchar[]之间的相互转换
参考3:Mat数据在Python和C++中传递

背景

python可以使用 ctypes 模块调用 c 函数、c 的变量类型(包括结构体类型、指针类型),但是ctype只支持C标准,所以一些C++的标准是不能用的,比如函数重载、Mat类型。Mat并不是c的语法,所以一般转换为uchar进行传递。
转换表:
类型映射表
python获取类型指针API
函数说明
Mat,uchar*,uchar[]之间的相互转换
在这里插入图片描述

Mat加载、结构体返回实现过程

首先在DLL文件中声明结构体并实现uchar*到Mat之间的转换,然后在python中定义一个类接收结构体,加载dll文件并定义函数输入输出参数,调用函数获取返回的结构体参数。详细请见代码

DLL(C++)

// Dll2.cpp: 定义 DLL 应用程序的导出函数。
#define EXPORT __declspec(dllexport)
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace cv;
using namespace std;

typedef struct NLDJ_TC_Out
{
    int test0;
    float test1;
    int test2[4];
}NLDJ_TC_Out;

class TestDLL {
public:
    void get_mat(uchar* matrix, int rows, int cols, int channels);
    uchar* send_mat();
};

void TestDLL::get_mat(uchar* matrix, int rows, int cols, int channels) {
    cout<<rows<<cols<<channels;
    Mat dst = Mat(Size(cols, rows), CV_8UC3, Scalar(255, 255, 255));
    dst.data = matrix;
    imshow("dst", dst);
    cv::waitKey(0);
}
# mat数据发送
uchar* TestDLL::send_mat(){
    Mat input_mat = imread("D:\\image\\bopian\\0.bmp");

    resize(input_mat, input_mat, Size(input_mat.cols / 4, input_mat.rows / 4), INTER_LINEAR);

    int height = input_mat.cols;//512
    int width = input_mat.rows;//612
    uchar* buffer = (uchar*)malloc(sizeof(uchar) * height * width*3);
    memcpy(buffer, input_mat.data, height * width * 3);
    return buffer;
}

extern "C" {
    TestDLL td;
    EXPORT NLDJ_TC_Out test_in(uchar* matrix, int rows, int cols, int channels) {
        td.get_mat(matrix,rows,cols,channels);

        // 返回结构体
        NLDJ_TC_Out result;
        result.test0 = 1;
        result.test1 = 2.2;
        for (int i = 0; i < 4; i++) {
            result.test2[i] = i;
        }
        return result;
    }
    EXPORT uchar* send_mat() {
        return td.send_mat();
    }
}

python调用代码


from ctypes import *
import cv2  # opencv读取的格式是BGR

# python中将结构体定义为类
class Struct_NLDJ_TC_Out(Structure):
    _fields_ = [("test0", c_int), ("test1", c_float), ("test2", c_int * 4)]

# dll加载,接口参数定义
lib = cdll.LoadLibrary("E:\\Dll1.dll")
lib.test_in.argtypes = (POINTER(c_ubyte), c_int, c_int, c_int)
lib.test_in.restype = Struct_NLDJ_TC_Out
lib.send_mat.restype = POINTER(c_ubyte)

# mat数据传入及结构体获取
img = cv2.imread('D:\\image\\bopian\\0.bmp')
img = cv2.resize(img, (0, 0), fx = 1 / 2, fy = 1 / 2)
cols = img.shape[1]
rows = img.shape[0]
channels = 3
pubyIm = img.ctypes.data_as(POINTER(c_ubyte))

# 调用DLL中函数
djTCVarOut = lib.test_in(pubyIm, rows, cols, channels)
print(djTCVarOut.test2[1])

# mat结构体获取
# 从指针指向的地址中读取数据,并转为numpy array
dll_mat = np.array(np.fromiter(pointer, dtype = np.uint8, count = 512 * 612 * 3))
dll_mat = dll_mat.reshape((512, 612, 3))
cv2.imshow('array_mat1', dll_mat)
cv2.waitKey()
  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值