merlinzjl

导航

C++ dll的创建和使用

在介绍Dll之前先了解下常见三种函数调用约定。

参考:https://www.cnblogs.com/yejianyong/p/7506465.html

我们使用的VS默认使用的函数调用约定是__cdel,而Windows API默认的调用约定是__stdcall。我们在使用一个dll的接口时,一定要确保你使用接口时的调用约定和接口定义时的调用约定一致。因为不同的调用约定,函数的栈内存释放的方式不同。

 

然后我们再了解下extern C的作用,参考https://www.cnblogs.com/carsonzhu/p/5272271.html

如果我们使用C++进行程序开发,开发过程中使用到了C语言写的库函数,则我们就需要使用extern C 来修饰,来告诉编译器,这部分代码使用C语言语法进行编译链接。

例如:

#ifdef __cplusplus

extern "C" {

#endif

#include "legacy_C_header.h"

#ifdef __cplusplus

}

#endif

这个就是它允许你在你的C ++代码中使用这个C头文件,因为宏“__cplusplus”将被定义。

 

下面我们开始学习C++Dll的创建和使用

C++创建的dll既可以给C++工程使用也可以给C#工程使用。

C++导出函数,在DLL中有一张导出表,记录着需要导出的函数,这些函数可供外部程序调用,即这些函数都是该DLL的入口点(类似main函数)。不在导出表中的函数,为该DLL私有的函数,外部程序不能调用它们。

 

C++工程调用C++导出函数或者导出类

导出函数的几个方法参考https://www.cnblogs.com/findumars/p/8660427.html

在函数声明时,直接使用__declspec(dllexport)声明函数

或者是直接使用def文件指定导出的函数

 

使用导出函数库时,我们可以直接在VS上配置,指定库目录和动态库对应的lib文件名,以及C/C++常规中的包含目录,该目录指定头文件。

 

 

 

 

 

 

也可以直接在代码中使用#pragma comment,具体语法可以参考https://blog.csdn.net/wfq_1985/article/details/7456591

使用如下:

#pragma comment(lib, "..\\CplusplusDll\\Debug\\CplusplusDll.lib")

 

当你不知道头文件只知道你使用的函数类型时,则可以使用如下函数:

typedef int(*func)(int, int); 

HINSTANCE hInstance = LoadLibrary(L"..\\CplusplusDll\\Debug\\CplusplusDll.dll");

LPCSTR pc = "?GetMax@@YAHHH@Z";

func getmax = (func)GetProcAddress(hInstance, pc);

int max = getmax(a, b);

 

使用微软VS提供的dumpbin –exports xxx.dll 可以查看你的函数名,同时你一定要确保你的调用约定和GetMax函数定义的一致。这里使用的是func的约定使用默认值一般是__cdel,函数GetMax定义的地方也是__cdel。如果是__stdcall则需要显示声明{typedef int(__stdcall*func)(int, int);}

注意,不建议直接使用这种方法对类的成员函数进行调用。

 

对于C++导出类,C++工程在调用时和导出函数一致,除了不能使用LoadLibrary函数进行动态加载外,VS配置和#progma预编译指令都可以使用。

#include "../CplusplusDll/CMath.h"

#pragma comment(lib, "..\\CplusplusDll\\Debug\\CplusplusDll.lib")

CMath m;

int sum = m.add(5, 6, 7);

 

 

对于C#工程,如何调用C++导出函数呢?使用DllImport属性,在System.Runtime.InteropServices命名空间下定义。参考https://www.cnblogs.com/xingboy/p/11158487.html,使用如下

 [DllImport(@"CplusplusDll.dll",CallingConvention = CallingConvention.Cdecl,EntryPoint = "?GetMax@@YAHHH@Z")]

public extern static int getMax(int a, int b);

int a = getMax(2, 3);

 

对于非托管的C++类,C#是无法直接使用,但是C#支持托管的C++代码的使用。所以非托管的C++类,可以通过托管类包装,进行导出,C++托管类使用的数据类型必须都是托管的,详情可以以下链接:https://blog.csdn.net/weixin_34167819/article/details/91974250

posted on 2019-11-04 23:57  merlinzjl  阅读(1927)  评论(0编辑  收藏  举报