VS 2015用C++项目生成dll并调用(2021.3.1)

Visual Studio 2015 C++支持的dll生成及调用 2021.3.1

  • 1、开发环境
  • 2、DLL介绍
  • 3、C++创建并调用自定义dll动态链接库(同一个解决方案下)
    • 3.1 新建C++项目来生成DLL
    • 3.2 新建客户端C++项目调用dll(同一解决方案下)
  • 4、C++项目本地调用dll(不同解决方案)
    • 4.1 将 DLL 标头(.h文件所在目录)添加到项目的包含目录
    • 4.2 将 DLL 导入库(.lib文件所在目录)添加到项目的库目录
    • 4.3 应用所调用dll(.dll文件)的本地部署
      • 4.3.1 手动复制dll
      • 4.3.2 在生成后事件中复制dll
  • 5、C#项目本地调用dll
    • 5.1 为C#项目进行dll的本地应用部署(两种dll文件复制方式)
      • 5.1.1 方式一:手动复制dll相关文件
      • 5.1.2 方式二:项目后期生成事件命令行复制

1、开发环境

        宇宙第一最强IDEVisual Studio 2015
VS 2015用C++项目生成dll并调用(2021.3.1)_第1张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第2张图片

2、DLL介绍

        在 Windows 中,动态链接库 (DLL) 是作为函数和资源的共享库的一种可执行文件。 动态链接是操作系统功能, 它可使执行文件调用函数或使用存储在单独文件中的资源。 可从使用这些函数和资源的可执行文件中对其分别进行编译和部署。
        DLL 不是独立的可执行文件。 DLL 在调用它们的应用程序的上下文中运行。 操作系统将 DLL 加载到应用程序的内存空间中。 此操作要么在加载应用程序时(隐式链接)完成,要么在运行时按需(显式链接)完成 。 DLL 还可以在可执行文件之间轻松共享函数和资源。 多个应用程序可同时访问内存中单个 DLL 副本的内容。
        静态链接将静态库中的所有对象代码复制到生成时使用它的可执行文件中。 动态链接仅包括 Windows 在运行时用于查找和加载含有数据项或函数的 DLL 所需的信息。 创建 DLL 时,还将创建包含此信息的导入库。 生成调用 DLL 的可执行文件时,链接器会使用导入库中的导出符号来为 Windows 加载程序存储此信息。 当加载程序加载 DLL 时,该 DLL 会映射到你的应用程序的内存空间中。 如果存在,则调用 DLL 中的特殊函数 DllMain,以执行 DLL 所需的任何初始化。
        尽管 DLL 和应用程序都是可执行文件模块,但它们之间也存在很多不同之处。 对用户来说,最明显的区别在于不能直接运行 DLL。 从系统的角度来看,应用程序和 Dll 之间有两个基本差异:
        是应用程序可以在系统中同时运行其自身的多个实例。 而 DLL 只能有一个实例。
        是应用程序可以作为进程进行加载。 它可以管理诸如堆栈、执行线程、全局内存、文件句柄和消息队列之类的资源。 而 DLL 不能管理这些资源。
        使用 DLL 的潜在缺点是,应用程序不是自包含的。 它依赖于一个独立的 DLL 模块的存在:在安装过程中必须亲自部署或验证的模块。

3、C++创建并调用自定义dll动态链接库(同一个解决方案下)

3.1 新建C++项目来生成DLL

        打开VS2015,菜单栏中找到文件并点击,弹出新建项目窗口,选择Visual C++下的Win32项目后再下方输入项目名称,浏览项目保存位置后点击确定,
VS 2015用C++项目生成dll并调用(2021.3.1)_第3张图片

VS 2015用C++项目生成dll并调用(2021.3.1)_第4张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第5张图片

VS 2015用C++项目生成dll并调用(2021.3.1)_第6张图片
        下面选择目标平台为Release和x64,然后在解决方案资源管理器下找到头文件,右键选择添加新建项,会弹出添加新项窗口,在添加新项窗口中选择头文件后输入名称为Mydll.h并点击添加即可。
VS 2015用C++项目生成dll并调用(2021.3.1)_第7张图片

VS 2015用C++项目生成dll并调用(2021.3.1)_第8张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第9张图片
        在打开的Mydll.h文件中写入以下代码:

#pragma once
// 导出函数,使用“ _stdcall ” 标准调用
extern "C" _declspec(dllexport) int Add(int a, int b);
extern "C" _declspec(dllexport) int Minus(int a, int b);
extern "C" _declspec(dllexport) int Multiply(int a, int b);
extern "C" _declspec(dllexport) int Divide(int a, int b);
extern "C" _declspec(dllexport) void SayHello();

        接下来需要在解决方案资源管理器下找到源文件,右键选择添加新建项
VS 2015用C++项目生成dll并调用(2021.3.1)_第10张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第11张图片
        在打开的Mydll.cpp文件中编写自定义函数的实现代码如下:

#include 
using namespace std;
#include "Mydll.h"
int Add(int a, int b)
{
     
	return a + b;
}
int Minus(int a, int b)
{
     
	return a - b;
}
int Multiply(int a, int b)
{
     
	return a * b;
}
int Divide(int a, int b)
{
     
	if(b!=0) return a / b;
	else
	{
     
		std::cout << "除数为0!" << std::endl;
		return -1;
	}
}
void SayHello()
{
     
	std::cout << "Hello world!" << std::endl;
}

VS 2015用C++项目生成dll并调用(2021.3.1)_第12张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第13张图片
        Win+E打开系统的文件资源管理器查看生成的dll文件,发现在D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\Mydll\x64\Release文件夹下生成了6个文件,包括Mydll.dll、Mydll.exp、Mydll.iobj、Mydll.ipdb、Mydll.lib和Mydll.pdb
VS 2015用C++项目生成dll并调用(2021.3.1)_第14张图片
        而新建的Mydll.h头文件和Mydll.cpp源文件则保存到了Mydll项目的Mydll文件夹下,如下图所示。
VS 2015用C++项目生成dll并调用(2021.3.1)_第15张图片
        到此为止,自定义的dll相关文件就已经编译生成(Mydll.cpp为源文件就不提了),包括头文件Mydll.h库文件Mydll.libDLL文件Mydll.dll以及Mydll.expMydll.iobjMydll.ipdbMydll.pdb

3.2 新建客户端C++项目调用dll(同一解决方案下)

        首先需要明确上述已经生成了dll文件,但我们想要调用这个dll则只需要关注三个文件:Mydll.hMydll.libMydll.dll
        这里新建一个调用dll的C++控制台项目,与Mydll项目放到了同一个解决方案下,所以直接点击文件下的添加,选择新建项目,
VS 2015用C++项目生成dll并调用(2021.3.1)_第16张图片
        在添加新项目窗口中,点击Visual C++后选择右侧的Win32 控制台应用程序,输入项目名称为TestMydll后点击确定即可。
VS 2015用C++项目生成dll并调用(2021.3.1)_第17张图片
        点击下一步,选择空项目后确定
VS 2015用C++项目生成dll并调用(2021.3.1)_第18张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第19张图片
        在解决方案资源管理器下的TestMydll的源文件上右键点击添加,选择新建项,
VS 2015用C++项目生成dll并调用(2021.3.1)_第20张图片
        在添加新项窗口中,选择C++文件(.cpp)后输入名称为TestMydll.cpp后点击添加。
VS 2015用C++项目生成dll并调用(2021.3.1)_第21张图片
        首先在TestMydll.cpp中写入不涉及dll调用的C++基本代码:

#include 
using namespace std;
int main()
{
     
	int a = 1, b = 1;
	std::cout << "初始值为a="<<a <<",b="<< b << std::endl;
	system("pause");
	return 0;
}

        先在TestMydll项目上右键选择生成,生成后会产生D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\Mydll*x64\Release**目录。
VS 2015用C++项目生成dll并调用(2021.3.1)_第22张图片

        在解决方案资源管理器中将TestMydll项目设为启动项目后就可以后启动本地调试,调试结果如下所示
VS 2015用C++项目生成dll并调用(2021.3.1)_第23张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第24张图片
        调试成功
VS 2015用C++项目生成dll并调用(2021.3.1)_第25张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第26张图片
        下面为TestMydll客户端项目设置所调用dll的包含目录和库目录,在解决方案资源管理器下的TestMydll项目上右键选择属性,打开TestMydll项目的属性页,在配置属性的VC++目录下,将包含目录设置为Mydll.h所在文件夹,将库目录设置为Mydll.lib所在文件夹
VS 2015用C++项目生成dll并调用(2021.3.1)_第27张图片
        同时在TestMydll属性页窗口下的链接器的输入中,附加依赖项设置为Mydll.lib
VS 2015用C++项目生成dll并调用(2021.3.1)_第28张图片
        然后修改TestMydll.cpp代码来调用Mydll.dll里面的函数,并将Mydll.dll动态链接库文件复制到D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\Mydll\x64\Release目录下即可(因为这里Mydll项目和TestMydll项目在同一个解决方案下,所以Mydll.dll就和TestMydll.exe自动在同一个文件夹下了),最后在TestMydll项目上右键选择重新生成后启动本地Windows调试器即可成功运行。
        完整的调用dll代码如下:

#include 
using namespace std;
#include "Mydll.h"
int main()
{
     
	int a = 100, b = 20;
	std::cout << "初始值为a=" << a << ",b=" << b << std::endl;
	std::cout << Add(a, b) <<std::endl;
	std::cout << Minus(a, b) << std::endl;
	std::cout << Multiply(a, b) << std::endl;
	std::cout << Divide(a, b) << std::endl;
	SayHello();
	system("pause");
	return 0;
}

VS 2015用C++项目生成dll并调用(2021.3.1)_第29张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第30张图片
        最后项目生成文件夹下的内容如下:
VS 2015用C++项目生成dll并调用(2021.3.1)_第31张图片

4、C++项目本地调用dll(不同解决方案)

        部署应用时,还必须部署它使用的 DLL。 若要使你生成的或从第三方加入的 DLL 可用于应用,最简单的方法就是将其放在应用所在的同一目录中。 这称为“应用本地部署” 。在本地部署中,库文件以及可执行文件安装在应用程序文件夹中。
        用VS 2015新建C++控制台项目,选择空项目后确定
VS 2015用C++项目生成dll并调用(2021.3.1)_第32张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第33张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第34张图片
        新建源文件C++TestMydll.cpp,并编写以下代码,同时选择Release和x64.

#include 
using namespace std;
#include "Mydll.h"
int main()
{
     
	int a = 100, b = 20;
	std::cout << "初始值为a=" << a << ",b=" << b << std::endl;
	std::cout << Add(a, b) <<std::endl;
	std::cout << Minus(a, b) << std::endl;
	std::cout << Multiply(a, b) << std::endl;
	std::cout << Divide(a, b) << std::endl;
	SayHello();
	system("pause");
	return 0;
}

VS 2015用C++项目生成dll并调用(2021.3.1)_第35张图片
        可以看到上图源代码中头文件和函数名称都标红,提示找不到,下面进行配置。

4.1 将 DLL 标头(.h文件所在目录)添加到项目的包含目录

        VS的解决方案中找到项目并右键选择属性,打开项目的属性页窗口,找到VC++目录的包含目录,将所调用dll对应的.h文件所在目录(D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\Mydll\Mydll)复制到这里。
VS 2015用C++项目生成dll并调用(2021.3.1)_第36张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第37张图片

4.2 将 DLL 导入库(.lib文件所在目录)添加到项目的库目录

                VS的解决方案中找到项目并右键选择属性,打开项目的属性页窗口,找到VC++目录的库目录,将所调用dll对应的.lib文件所在目录(D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\Mydll\x64\Release)复制到这里。
VS 2015用C++项目生成dll并调用(2021.3.1)_第38张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第39张图片
        同时VS的解决方案中找到项目并右键选择属性,打开项目的属性页窗口,找到链接器的输入,右侧找到附加依赖项输入dll对应的.lib文件的文件名Mydll.lib
VS 2015用C++项目生成dll并调用(2021.3.1)_第40张图片
        这时代码就不会标红了,如下图所示,但如果直接运行会报错,并提示无法找到Mydll.dll文件
VS 2015用C++项目生成dll并调用(2021.3.1)_第41张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第42张图片

4.3 应用所调用dll(.dll文件)的本地部署

        一般来说,应用所调用dll文件的本地部署分为手动复制dll在生成后事件中复制dll两种方式。

4.3.1 手动复制dll

        将D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\Mydll\x64\Release\Mydll.dll文件复制到D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\C++TestMydll\x64\Release文件夹下,然后在VS中重新生成并启动本地调试器运行即可成功。
VS 2015用C++项目生成dll并调用(2021.3.1)_第43张图片

VS 2015用C++项目生成dll并调用(2021.3.1)_第44张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第45张图片

4.3.2 在生成后事件中复制dll

        通过解决方案资源管理器的C++TestMydll项目上右键,在配置属性的常规下可以看到输出目录为D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\C++TestMydll\x64\Release
VS 2015用C++项目生成dll并调用(2021.3.1)_第46张图片

        像 S o l u t i o n 、 Solution、 SolutionPlatform、 C o n f i g u r a t i o n 和 Configuration和 ConfigurationOutDir等宏变量都表示特定的文件目录。
VS 2015用C++项目生成dll并调用(2021.3.1)_第47张图片
        首先删除D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\C++TestMydll\x64\Release文件夹下的Mydll.dll文件,然后在项目上右键打开属性页窗口,找到生成事件->后期生成事件,命令行中输入以下命令将Mydll.dll文件在项目运行后期自动复制到项目x64\Release文件夹下:
VS 2015用C++项目生成dll并调用(2021.3.1)_第48张图片

xcopy /y /d "..\..\Mydll\$(IntDir)Mydll.dll" "$(OutDir)"

VS 2015用C++项目生成dll并调用(2021.3.1)_第49张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第50张图片
        此时启动本地调试器即可成功运行,同时可以看到Mydll.dll文件会被自动复制到C++TestMydll项目的x64\Release文件夹下
VS 2015用C++项目生成dll并调用(2021.3.1)_第51张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第52张图片

5、C#项目本地调用dll

        不像C++项目调用自定义dll那样复杂,C#调用自定义dll只需将所有dll相关的生成文件放到自己的生成文件夹下同时在代码中添加dll自定义函数导入声明即可。
        首先,新建一个C#控制台应用程序
VS 2015用C++项目生成dll并调用(2021.3.1)_第53张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第54张图片
        现在需要在主函数main内部添加两行代码后,解决方案配置选择Release解决方案平台选择x64后,点击启动本地调试器开始运行:

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

namespace CSharpConsoleApplication
{
     
    class Program
    {
     
        static void Main(string[] args)
        {
     
            Console.WriteLine("This is a CSharp Console Application!");
            Console.ReadLine();
        }
    }
}

VS 2015用C++项目生成dll并调用(2021.3.1)_第55张图片

VS 2015用C++项目生成dll并调用(2021.3.1)_第56张图片
        接下来在代码中添加dll引用接口,并在代码的主函数外添加dll自定义函数导入声明,在主函数内部添加函数调用代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;//添加dll引用接口

namespace CSharpConsoleApplication
{
     
    class Program
    {
     
        //添加dll自定义函数导入声明
        [DllImport("Mydll.dll", EntryPoint = "Add")]
        static extern int Add(int a, int b);

        [DllImport("Mydll.dll", EntryPoint = "Minus")]
        static extern int Minus(int a, int b);

        [DllImport("Mydll.dll", EntryPoint = "Multiply")]
        static extern int Multiply(int a, int b);

        [DllImport("Mydll.dll", EntryPoint = "Divide")]
        static extern int Divide(int a, int b);

        [DllImport("Mydll.dll", EntryPoint = "SayHello")]
        static extern void SayHello();

        static void Main(string[] args)
        {
     
            int a = 50, b = 5;
            Console.WriteLine("This is a CSharp Console Application!");
            Console.WriteLine(Add(a, b));
            Console.WriteLine(Minus(a, b));
            Console.WriteLine(Multiply(a, b));
            Console.WriteLine(Divide(a, b));
            SayHello();//添加函数调用代码
            Console.ReadLine();
        }
    }
}

VS 2015用C++项目生成dll并调用(2021.3.1)_第57张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第58张图片
        这时如果直接启动本地调试器开始运行,结果不会成功,因为Mydll.dll相关文件还没有对CSharpApplication项目进行本地部署,会如上图所示报错,提示无法加载Mydll.dll文件。

5.1 为C#项目进行dll的本地应用部署(两种dll文件复制方式)

        为C#项目部署本地应用的dll相关文件只涉及到Mydll.dll、Mydll.exp、Mydll.iobj、Mydll.ipdb、Mydll.lib和Mydll.pdb六个文件。

5.1.1 方式一:手动复制dll相关文件

        将D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\Mydll\x64\Release文件夹下的上述六个文件手动复制到D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\CSharpConsoleApplication\CSharpConsoleApplication\bin\x64\Release文件夹下即可,然后在VS2015中启动本地调试器即可成功运行。
VS 2015用C++项目生成dll并调用(2021.3.1)_第59张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第60张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第61张图片

5.1.2 方式二:项目后期生成事件命令行复制

        首先保证D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\CSharpConsoleApplication\CSharpConsoleApplication\bin\x64\Release文件夹下没有Mydll.dll相关的文件即可
VS 2015用C++项目生成dll并调用(2021.3.1)_第62张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第63张图片
        将C++项目自定义生成文件夹下dll相关文件复制到C#项目生成文件夹下的命令行代码,需要在CSharpApplication项目上右键->属性打开相关设置窗口,找到生成事件,在生成事件的后期生成事件命令行中输入如下代码后启动本地调试器即可成功运行。

xcopy /y /d "D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\Mydll\x64\Release\*.*" "D:\Program Files (x86)\Microsoft Visual Studio 2015\myprojects\CSharpConsoleApplication\CSharpConsoleApplication\bin\x64\Release\"

VS 2015用C++项目生成dll并调用(2021.3.1)_第64张图片
VS 2015用C++项目生成dll并调用(2021.3.1)_第65张图片
在这里插入图片描述

你可能感兴趣的:(VS,2015配置ArcGIS,Engine,10.2开发环境搭建,vs2015,C++,DLL,c#)