> 文章列表 > c# 调用c++ 动态链接库

c# 调用c++ 动态链接库

c# 调用c++ 动态链接库

1、动态链接库概述:

  • 动态链接库通常都不能直接运行,也不能接受消息;只有在其他模块调用动态链接库中的函数时,它才发挥作用。
  • Windows API中所有的函数都包含在动态链接库中。
  • 动态链接库分静态库和动态库。

2、导出函数的声明方式

1)强制用C语言方式进行修饰,且用C的默认调用约定,即__cdecl方式。这种方式编译产生的DLL中有一个导出函数:add,不加任何修饰。(这种方式最好)

extern "C" int __declspec(dllexport) add();

2)强制用C语言方式进行修饰,且用__stdcall约定。这种方式编译产生的DLL中有一个导出函数:_add@0,即前面有“_”,后面加了参数长。

extern "C" int __declspec(dllexport) __stdcall add();

3)不强制用C语言方式进行修饰,但是用__stdcall约定。这种方式编译产生的DLL中有一个导出函数:?add@@YGHXZ。这个名字很怪,后面的不好理解。

int __declspec(dllexport) __stdcall add();

4)不强制用C语言方式进行修饰,并且用 __cdecl 约定。这种方式编译产生的DLL中有一个导出函数:?add@@YAHXZ。注意看,和第三种方有一点不同。

int __declspec(dllexport) __cdecl add();

  对于DLL导出函数声明的四种写法,在动态调用时, 声明成第一种方式是最好的。但是,C/C++缺省的调用约定为__cdecl约定,如果想别的语言能用DLL的话,最好是将调用约定写成__stdcall方式(不能动态调用),然后静态(隐式)调用。
  在隐式调用时,四种声明方式都是可以的,只要调用者的声明方式和DLL声明时的方式一致即可。

pch.h 头文件#pragma once
extern "C" _declspec(dllexport) int Sum(int a, int b);pch.cpp 代码文件#include "pch.h"
#include "iostream"
#include <opencv2/opencv.hpp>
#include <iostream>using namespace cv;
using namespace std;int Sum(int a, int b)
{if (a - (int)a != 0 || b - (int)b != 0){cout << "请输入整数" << endl;return -1;}return a + b;
}extern "C"
{__declspec(dllexport)Mat* ResizeMat(Mat* mat){Mat* result = new Mat();cv::resize(*mat, *result, Size(), 0.5, 0.5, INTER_AREA);return result;}
}

c#调用代码如下:

using OpenCvSharp;
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;namespace DllTest
{public partial class Form1 : Form{[DllImport(@"CreateDLL.dll")]public static extern int Sum(int a, int b);[DllImport("CreateDLL.dll", EntryPoint = "ResizeMat")]private static extern IntPtr ResizeMatNative(IntPtr matPtr);public Form1(){InitializeComponent();}private void Form1_Load(object sender, EventArgs e){int d = Sum(3, 4);Mat mat = new Mat("152237.jpg");IntPtr matPtr = mat.CvPtr;IntPtr resultPtr = ResizeMatNative(matPtr);Mat result = new Mat(resultPtr);result.SaveImage("output.jpg");}}
}