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");
}
}
}