一、简单使用
ctypes — Python 的外部函数库 【中文文档】 字符串传递
ctypes 定义了一些和C兼容的基本数据类型:
#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;
}
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
from ctypes import *
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);
cv::circle(src, cv::Point(60, 60), 10, cv::Scalar(255, 0, 0));
memcpy(ret_data, src.data, rows * cols * 3);
}
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))
MYDLL.mattostring.restype = 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))
size = c_int(0)
a = MYDLL.mattostring(srcPointer,rows,cols,byref(size))
print("[size]=",size.value)
b = string_at(a,size.value)
nparr = np.frombuffer(b, np.uint8)
img_decode= cv2.imdecode(nparr,cv2.IMREAD_COLOR)
cv2.imshow("img_decode", img_decode)
cv2.waitKey(0)
cv2.destroyAllWindows()
img_decode=Image.fromarray(img_decode[:,:,::-1])
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])
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;
}
|