通过swig封装c++代码来扩展python库以读取共享内存中的图片

上面我的博客C#共享内存方式读写数据及图像_jiugeshao的专栏-CSDN博客演示了c#往共享内存里写入图片和读取图片,接下来讲解如何用python去读取由c#写入到共享内存里的图片。

1. 创建两个文件example.h和example.cpp。(两个文件如何创建及代码中引用路径说明见下面,不要懵圈了)

example.h中代码如下:

#pragma once
#include <Python.h>
#include <iostream>
#include <string>
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\ndarrayobject.h>
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\arrayobject.h>

using namespace std;

void say_hello();
int add(int a, int b);
int sub(int a, int b);
PyObject* GetImageFromSM(const char* sharedMemoryName, int height, int width, int channel);

example.cpp中代码如下:

#include "example.h"
#include <windows.h>

void say_hello()
{
	std::cout << "hello" << std::endl;
 }

int add(int a, int b)
{
	return(a + b);
 }

int sub(int a, int b)
{
    return(a - b);
 }

LPCWSTR sToW(std::string src)
{
	size_t srcsize = src.length() + 1;
	size_t c = 0;
	wchar_t *wc = new wchar_t[srcsize];
	mbstowcs_s(&c, wc, srcsize, src.c_str(), _TRUNCATE);

	return wc;
}

PyObject* GetImageFromSM(const char* sharedMemoryName, int height, int width, int channel)
{
	//channel表示为通道数,支持1和3
	Py_Initialize();

	if (!Py_IsInitialized())
	{
		std::cout << "error";
	}
	std::cout << "start to get image from sharememory" << std::endl;
	if (PyArray_API == NULL)
	{
		import_array();
	}
	std::string MN = sharedMemoryName;

	LPCWSTR MemoryName_lpcwstr = sToW(MN);
	std::cout << MN << std::endl;
	std::cout << MemoryName_lpcwstr << std::endl;

	HANDLE shareMemoryMap = NULL;
	shareMemoryMap = ::OpenFileMappingW(FILE_MAP_ALL_ACCESS, 0, MemoryName_lpcwstr);

	delete[] MemoryName_lpcwstr;
	MemoryName_lpcwstr = NULL;

	int DataLength = width * height * channel;
	std::cout << "Data Length: " << DataLength << std::endl;

	LPVOID pData = nullptr;
	pData = ::MapViewOfFile(shareMemoryMap, FILE_MAP_ALL_ACCESS, 0, 0, DataLength);
	if (pData != NULL)
	{
		std::cout << "share memory has been created" << std::endl;
	}
	else
	{
		std::cout << "error" << std::endl;
	}

	PyObject* numpyData = nullptr;
	npy_intp nd[3] = { 0, 0, 0 };
	if (channel == 1)
	{
		//单通道灰度图
		std::cout << "channel 1" << std::endl;
		nd[0] = height;
		nd[1] = width;
		numpyData = PyArray_SimpleNewFromData(2, nd, NPY_UBYTE, pData);
		
	}
	else
	{
		//三通道彩色图
		std::cout << "channel 3" << std::endl;
		nd[0] = height;
		nd[1] = width;
		nd[2] = 3;
		numpyData = PyArray_SimpleNewFromData(3, nd, NPY_UBYTE, pData);
		
	}

	std::cout << "over" << std::endl;
	return numpyData;
}

这两个文件你可以直接用txt文本编写,因为并不依赖vs编译器去编译生成一个什么东西(比如pyd),但txt写的话,你不容易发现你的语法错误,所以还是推荐使用vs.

example.h中引用的头文件路径是根据自己的环境所配置的,我的Anaconda3安装在C盘根目录下,所以这边根据自己的路径做相应改变。既然使用vs来编辑example.h和example.cpp文件,所以可以建立一个空的c++控制台程序,并对此工程进行环境配置,如下是我所建立的工程,进行环境配置也是为了一方面方便直接在c++里做一些测试。

2.下载swig软件,版本是4.0.1,链接如下

链接:https://pan.baidu.com/s/1E3NICbCRt-oqD0oOVZw54Q 
提取码:3va1 


3. 添加如下环境变量(我的文件在D盘根目录下)

D:\swigwin-4.0.1 (1)\swigwin-4.0.1

4. 编写example.i文件,此文件和example.h和example.cpp在一个目录下

%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\ndarrayobject.h>
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\arrayobject.h>
using namespace std;
%}
%include "example.h"
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\ndarrayobject.h>
#include <C:\Anaconda3\Lib\site-packages\numpy\core\include\numpy\arrayobject.h>

5.cmd命令到example.i所在文件夹路径下,通过使用

swig -python -c++ example.i

命令行(管理员身份运行cmd)来生成对应的.cxx和.py文件

6. 编写setup.py文件,如下:

#!/usr/bin/env python

"""
setup.py file for SWIG C\+\+/Python example
"""
from distutils.core import setup, Extension
example_module = Extension('_example',
sources=['example.cpp', 'example_wrap.cxx',],
)
setup (name = 'example',
version = '0.1',
author = "www",
description = """Simple swig C\+\+/Python example""",
ext_modules = [example_module],
py_modules = ["example"],
)

6. 完毕后管理员身份运行Anaconda Prompt, 通过使用

python setup.py build_ext --inplace

命令来生成_example模块

生成完毕后,该路径下相关的文件如下

编写test_example.py(和前面生成的pyd文件一个路径)以来验证是否生成的_example模块能否被正确调用,同时验证是否可以读取c#写到共享内存中的图片

import example
from PIL import Image, ImageStat
example.say_hello()
c = example.add(3,4)
e = example.sub(4,5)
im = example.GetImageFromSM("img",375,500,3)
im = im[...,::-1]
x = Image.fromarray(im, 'RGB')

x.show()
print(c)
print(e)

7.运行上一篇博客的程序,使用c#往共享内存里写入一张彩色图像

8.运行上面的test_example.py文件,结果如下:

到这里可以看到python已经可以读取c#往共享内存里存入的一张图片了。

接下来会在我的该系列博客第5篇C#和python通过socket方法进行通信_jiugeshao的专栏-CSDN博客基础上,完善该篇博客中的程序,使得c#可以通过调用python来完成模型的训练,训练完毕后可以实时预测一张图像的结果。

Guess you like

Origin blog.csdn.net/jiugeshao/article/details/111946360
Recommended