IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> python 使用ctypes加载(C/C++)动态库 -> 正文阅读

[C++知识库]python 使用ctypes加载(C/C++)动态库

一、简单使用

ctypes — Python 的外部函数库 【中文文档】
字符串传递

ctypes 定义了一些和C兼容的基本数据类型:

ctypes 类型C 类型Python 类型
c_bool_Boolbool (1)
c_charchar单字符字节串对象
c_wcharwchar_t单字符字符串
c_bytecharint
c_ubyteunsigned charint
c_shortshortint
c_ushortunsigned shortint
c_intintint
c_uintunsigned intint
c_longlongint
c_ulongunsigned longint
c_longlong__int64 或 long longint
c_ulonglongunsigned __int64 或 unsigned long longint
c_size_tsize_tint
c_ssize_tssize_tPy_ssize_tint
c_floatfloatfloat
c_doubledoublefloat
c_longdoublelong doublefloat
c_char_pchar* (以 NUL 结尾)字节串对象或 None
c_wchar_pwchar_t* (以 NUL 结尾)字符串或 None
c_void_pvoid*int 或 None
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>

#define DLLEXPORT extern "C" __declspec(dllexport)  
DLLEXPORT float __stdcall add(int a, float b) {
	printf("a=%d\n", a);
	printf("b=%f\n", b);
	return a + b;
}


DLLEXPORT char* __stdcall get_ascii_str(char* path)
{
	std::cout << "path:" << path << std::endl;
	char* ret;
	ret = (char*)malloc(24);
	strcpy(ret, "hello word123,./");
	return ret;
}


DLLEXPORT char* __stdcall get_utf8_str(char* path)
{
	std::cout << "path:" << path << std::endl;
	char* ret;
	ret = (char*)malloc(24);
	strcpy(ret, "你好hello word123,./");
	return ret;
}


//构建字符串数组,2个元素
typedef struct struct_str_arr
{
	const char* str_ptr[2];
} str_arr;

struct_str_arr* str_arr_ptr = (struct_str_arr*)malloc(sizeof(str_arr));

DLLEXPORT struct_str_arr* __stdcall get_str_list(int n, char* b[2])
{
	for (int i = 0; i < n; i++)
	{
		printf("%s", *(b + i));
		printf("\n");
	}
	str_arr_ptr->str_ptr[0] = "你好";
	str_arr_ptr->str_ptr[1] = "hell";
	return str_arr_ptr;
}

test.py

# -*- coding: utf-8 -*-
from ctypes import *

# ==================================
# dll =CDLL("./ctype_test1.dll")
# dll = cdll.LoadLibrary("./ctype_test1.dll")
# dll = windll.LoadLibrary("./ctype_test1.dll")
# ==================================

dll = PyDLL("./ctype_test1.dll")
dll.add.argtypes=[c_int,c_float]
dll.add.restype=c_float
a=c_int(10)
b=c_float(20.5)
res= dll.add(a,b)
print(res)


print("#######################################")
dll.get_ascii_str.argtypes=[c_char_p]
dll.get_ascii_str.restype=c_char_p

tex= b"dsf123,./"
text = c_char_p(tex)
rt_str=dll.get_ascii_str(text)
print(rt_str)


dll.get_utf8_str.argtypes=[c_char_p]
dll.get_utf8_str.restype=c_char_p

tex= "你好呀dsf123,./".encode()
text = c_char_p(tex)

rt_str=dll.get_utf8_str(text)
print(rt_str.decode('gbk'))


print("#######################################")
# 返回的数据
class StructPointer(Structure):  
    _fields_ = [("str_ptr", c_char_p * 2)]  


dll.get_str_list.restype = POINTER(StructPointer)
str1 = c_char_p(bytes("nihao", 'utf-8'))
str2 = c_char_p(bytes("shijie", 'utf-8'))
a = (c_char_p*2)(str1, str2)
ret_ptr =dll.get_str_list(2, a)
print(ret_ptr.contents.str_ptr[0].decode("gbk"))
print(ret_ptr.contents.str_ptr[1].decode("gbk"))

二、结构体

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <iostream>
#include <opencv2/opencv.hpp>


#ifdef _MSC_VER
#define DLL_EXPORT extern "C" __declspec(dllexport) 
#else
#define DLL_EXPORT extern "C"
#endif


DLL_EXPORT float __stdcall add(int a, float b) {
	printf("a=%d\n", a);
	printf("b=%f\n", b);
	return a + b;
}


DLL_EXPORT void add_point(float* a, float* b, float* c)
{
	*c = *a + *b;
	*a = 129.7;
}


//作为返回值返回
DLL_EXPORT uchar* mattostring(uchar* src_data, int rows, int cols, int* size)
{
	cv::Mat dst = cv::Mat(cv::Size(cols, rows), CV_8UC3, cv::Scalar(255, 255, 255));
	dst.data = src_data;
	circle(dst, cv::Point(60, 60), 10, cv::Scalar(255, 0, 0));

	std::vector<uchar> data_encode;
	cv::imencode(".png", dst, data_encode);
	std::string str_encode(data_encode.begin(), data_encode.end());
	uchar* char_r = new uchar[str_encode.size() + 10];
	*size = str_encode.size() + 10;
	memcpy(char_r, str_encode.data(), sizeof(char) * (str_encode.size()));
	return char_r;
}

//作为入参指针传递
DLL_EXPORT void draw_circle(int rows, int cols, unsigned char* src_data, unsigned char* ret_data)
{
	cv::Mat src = cv::Mat(rows, cols, CV_8UC3, src_data);           // uchar* 转cvMat
	cv::circle(src, cv::Point(60, 60), 10, cv::Scalar(255, 0, 0));  // 画图
	memcpy(ret_data, src.data, rows * cols * 3);                    // 将Mat转换成unsigned char
}

test.py

from ctypes import *
import cv2
import numpy as np
from PIL import Image

MYDLL= CDLL("./x64/Release/ctype_test2.dll", winmode=0)



x1 = c_float(1.9)
x2 = c_float(10.1)
x3 = c_float(0)
MYDLL.add_point(byref(x1),byref(x2),byref(x3))
print("x1=",x1)
print("x2=",x2)
print("x3=",x3)


image=cv2.imread("./20220818142610.png")
rows = image.shape[0]
cols = image.shape[1]
channels =3
print("[cols*rows*channels]",cols*rows*channels)


MYDLL.mattostring.argtypes = (POINTER(c_ubyte), c_int,c_int, POINTER(c_int))  # c_char_p也可以
MYDLL.mattostring.restype = c_void_p                                          # POINTER(c_ubyte) 跟c_void_p都可以
#MYDLL.mattostring.restype = POINTER(c_uint64)                                # POINTER(c_ubyte) 跟c_void_p都可以
MYDLL.draw_circle.argtypes=[c_int,c_int,POINTER(c_ubyte),POINTER(c_ubyte)]
MYDLL.draw_circle.restype=c_void_p



srcPointer=image.ctypes.data_as(POINTER(c_ubyte))    #方式1.1
# srcPointer=image.ctypes.data_as(c_char_p)          #方式1.2
# srcPointer = image.astype(np.uint8).tostring()     #方式2

size = c_int(0)
a = MYDLL.mattostring(srcPointer,rows,cols,byref(size))
#b = string_at(a,cols*rows*channels)                 # 类似于base64
print("[size]=",size.value)
b = string_at(a,size.value)                          # 类似于base64
# b = string_at(a,99132)                             # 类似于base64

nparr = np.frombuffer(b, np.uint8)
img_decode= cv2.imdecode(nparr,cv2.IMREAD_COLOR)     #转cvMat
cv2.imshow("img_decode", img_decode) 
cv2.waitKey(0)
cv2.destroyAllWindows()
img_decode=Image.fromarray(img_decode[:,:,::-1])     # 由于直接cv2.imshow()显示出来的图是错误的,保存或者转为Image格式,显示正确
img_decode.show()


ret_img = np.zeros(dtype=np.uint8, shape=(rows, cols, 3))
retPoint = ret_img.ctypes.data_as(POINTER(c_ubyte))
MYDLL.draw_circle(rows, cols, srcPointer, retPoint)
cv2.imshow("ret_img", ret_img) 
cv2.waitKey(0)
cv2.destroyAllWindows()

ret_img_out = Image.fromarray(ret_img[:,:,::-1])  # 参数指针传递,不需要从uchar*转换,只需要取他的源头数据即可.
ret_img_out.show()

三、Mat2string

#include <iostream>
#include <memory.h>
#include <string>
#include <opencv2/opencv.hpp>



void Mat_to_string(cv::Mat& image, std::string& Imagestring) 
{
	std::vector<uchar> buff;
	cv::imencode(".jpg", image, buff);
	std::string image_string(reinterpret_cast<char*>(&buff[0]), buff.size());
	Imagestring = image_string;
}


void string_to_Mat(std::string& Imagestring, cv::Mat& image)
{
	std::vector<char> vec_data(Imagestring.c_str(), Imagestring.c_str() + Imagestring.size());
	cv::Mat dst = cv::imdecode(vec_data, cv::IMREAD_UNCHANGED);
	image = dst;
}


int main(int argc, char* argv[])
{
	cv::Mat image = cv::imread("E:\\Desktop\\20220818142610.png");
	if (image.empty())
	{
		std::cout << "image is empty" << std::endl;
	}

	std::string Imagestring;
	Mat_to_string(image, Imagestring);
	cv::Mat dst;
	string_to_Mat(Imagestring, dst);

	cv::imshow("dst", dst);
	cv::waitKey(0);
	cv::destroyAllWindows();
	return 0;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-21 00:08:17  更:2022-09-21 00:09:26 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:04:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码