C# 调用C++编写DLL

C# 调用C++编写DLL

做大神的搬运工 如有侵权请联系我删除
点击这里

使用过程中出现了报错情况:
System.BadImageFormatException

点击这里

补充使用:
问题点:结构体方式传递数据,非常方便。但是会出现报错的情况.
“无法封送处理“parameter #1”: 内部限制: 结构太复杂或太大。”
使用指针传递数据大数据;(图片等数据)

C++ DLL部分

创建的头文件 MagicStickDll.h

#pragma once

//图片信息
struct ImageInfo
{
public:
	int width;
	int height;
	int nBandNum;
};

//设置图片 参数使用了 结构体与 指针;
extern "C" _declspec(dllexport)  void __stdcall SetImageData(ImageInfo& imageInfo, BYTE* pImage);

MagicStickDll.cpp

// MagicStickDll.cpp : 定义 DLL 应用程序的导出函数。
//
#include 
#include 

using namespace std;

#include "stdafx.h"
#include "MagicStickDll.h"

//************************************
// Method:    TransBufferToMat
// FullName:  图片buffer数据转换成 Mat数据格式;
// Access:    public 
// Returns:   cv::Mat
// Qualifier:
// Parameter: unsigned char * pBuffer  图片数据内容
// Parameter: int nWidth	图片的宽度
// Parameter: int nHeight  图片的高度
// Parameter: int nBandNum 每个像素包含数据个数 (1, 3, 4 ) 1:Gray 3:RGB 4:RGBA
// Parameter: int nBPB  每个像素数据 所占位数(1, 2) 1:8位  2:16位;
//************************************
cv::Mat TransBufferToMat(BYTE* pBuffer, int nWidth, int nHeight, int nBandNum, int nBPB = 1)
{
	cv::Mat mDst;
	if (nBandNum == 4)
	{
		if (nBPB == 1)
		{
			mDst = cv::Mat::zeros(cv::Size(nWidth, nHeight), CV_8UC4);
		}
		else if (nBPB == 2)
		{
			mDst = cv::Mat::zeros(cv::Size(nWidth, nHeight), CV_16UC4);
		}
	}
	else if (nBandNum == 3)
	{
		if (nBPB == 1)
		{
			mDst = cv::Mat::zeros(cv::Size(nWidth, nHeight), CV_8UC3);
		}
		else if (nBPB == 2)
		{
			mDst = cv::Mat::zeros(cv::Size(nWidth, nHeight), CV_16UC3);
		}
	}
	else if (nBandNum == 1)
	{
		if (nBPB == 1)
		{
			mDst = cv::Mat::zeros(cv::Size(nWidth, nHeight), CV_8UC1);
		}
		else if (nBPB == 2)
		{
			mDst = cv::Mat::zeros(cv::Size(nWidth, nHeight), CV_16UC1);
		}
	}

	for (int j = 0; j < nHeight; ++j)
	{
		BYTE* data = mDst.ptr<BYTE>(j);
		BYTE* pSubBuffer = pBuffer + (nHeight - 1 - j) * nWidth* nBandNum*nBPB;
		memcpy(data, pSubBuffer, nWidth*nBandNum*nBPB);
	}
	if (nBandNum == 1)
	{
		cv::cvtColor(mDst, mDst, cv::COLOR_GRAY2BGR);
	}
	else if (nBandNum == 3)
	{
		cv::cvtColor(mDst, mDst, cv::COLOR_RGB2BGR);
	}
	else if (nBandNum == 4)
	{
		cv::cvtColor(mDst, mDst, cv::COLOR_RGBA2BGR);
	}

	return mDst;
}

//设置图片;
void __stdcall SetImageData(ImageInfo& imageInfo, BYTE* pImage)
{
	cv::Mat  colorImage = TransBufferToMat(pImage, imageInfo.width, imageInfo.height, imageInfo.nBandNum);

 	//显示图片数据;
	cout << "宽度" << imageInfo.width << endl;
 	cout << "高度" << imageInfo.height << endl;
 
	cv::imshow("彩色图片", colorImage);
	cv::waitKey(0);

}

stdafx.h


#pragma once

#include "targetver.h"

#define WIN32_LEAN_AND_MEAN             // 从 Windows 头中排除极少使用的资料
// Windows 头文件: 
#include 


#include "MagicStickDll.h"

MyDll.def

LIBRARY "MagicStickDll"

EXPORTS

SetImageData @ 1

C# 调用侧

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;

namespace MagicStickTester
{
    class Program
    {
        //Dll函数导出;

        //设置图片数据; dll位置根据实际清空设置;
        [DllImport(@"../../../x64/Debug/MagicStickDll.dll", EntryPoint = "SetImageData", SetLastError = true,
        CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        public extern static void SetImageData(ref ImageInfo imageData, [MarshalAs(UnmanagedType.LPArray)]byte[] groupVal);


        public static void SetImage(ref byte[] imageData)
        {
            int size = imageData.Length;

            int width = 300;
            int height = 200;
            int nBandNum = 4;

            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    if (j < 100)
                    {
                        imageData[i * width * nBandNum + j * nBandNum] = 255;
                        imageData[i * width * nBandNum + j * nBandNum + 1] = 0;
                        imageData[i * width * nBandNum + j * nBandNum + 2] = 0;
                        imageData[i * width * nBandNum + j * nBandNum + 3] = 0;
                    }
                    else if (100 <= j && j < 200)
                    {
                        imageData[i * width * nBandNum + j * nBandNum] = 0;
                        imageData[i * width * nBandNum + j * nBandNum + 1] = 255;
                        imageData[i * width * nBandNum + j * nBandNum + 2] = 0;
                        imageData[i * width * nBandNum + j * nBandNum + 3] = 0;
                    }
                    else if (j >= 200)
                    {
                        imageData[i * width * nBandNum + j * nBandNum] = 0;
                        imageData[i * width * nBandNum + j * nBandNum + 1] = 0;
                        imageData[i * width * nBandNum + j * nBandNum + 2] = 255;
                        imageData[i * width * nBandNum + j * nBandNum + 3] = 0;
                    }
                }
            }

        }

        static void Main(string[] args)
        {
            //设置图片基本信息 宽、高、像素位数
            ImageInfo imageInfo = new ImageInfo();
            imageInfo.width = 300;
            imageInfo.height = 200;
            imageInfo.nBandNum = 4;

            //设置图片数据内容;
            int imageSize = imageInfo.width * imageInfo.height * imageInfo.nBandNum;
            byte[] imageBytes = new byte[imageSize];
            SetImage(ref imageBytes);

            //调用DLL中函数, 
            SetImageData(ref imageInfo, imageBytes);
        }

        //导出 Dll内结构体;
        [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
        public struct ImageInfo
        {
            public int width;       //图片宽度;
            public int height;      //图片高度;
            public int nBandNum;    //像素大小;
        };

    }
}

复杂结构体使用

大神参考 这里

C++代码侧 结构体定义

//图片路径;
struct ImagePath
{
	char inputFilename[256];	//输入文件路径;
};

//图片路径数组;
struct InputImagePaths
{
	ImagePath imagePaths[50];
};

C++代码侧 函数定义与使用

//设置字符串
extern "C" _declspec(dllexport)
void __stdcall AddImagePath(InputImagePaths& imagePaths, int nLength);
void __stdcall AddImagePath(InputImagePaths& imagePaths, int nLength)
{
	for (int i = 0; i < nLength; i++)
	{
		string strImage = imagePaths.imagePaths[i].inputFilename;
	}
}

C# 代码 结构体定义

    [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
    public struct ImagePath
    {
        [System.Runtime.InteropServices.MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string inputFilename;  
    };

    [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
    public struct InputImagePaths
    {
        [System.Runtime.InteropServices.MarshalAs(UnmanagedType.ByValArray, SizeConst = 50)]
        public ImagePath[] imagePaths;
    };

C# 代码 函数定义与使用

        [DllImport(@"CameraCalibration.dll", EntryPoint = "AddImagePath", SetLastError = true,
        CharSet = CharSet.Unicode, ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
        public extern static void AddImagePath(ref InputImagePaths imagePaths, int nLength);
        InputImagePaths inputImagePaths = new InputImagePaths();
        inputImagePaths.imagePaths = new ImagePath[50];
        inputImagePaths.imagePaths[0].inputFilename = "..\\bin\\01.bmp";
        inputImagePaths.imagePaths[1].inputFilename = "..\\bin\\02.bmp";
        inputImagePaths.imagePaths[2].inputFilename = "..\\bin\\03.bmp";
        CameraCalibration.AddImagePath(ref inputImagePaths, 3);

你可能感兴趣的:(C#,OpenCV-C++)