IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C#【必备技能篇】VS2019 使用C/C++ 生成DLL 文件,并用 C/C++、C#调用DLL -> 正文阅读

[C++知识库]C#【必备技能篇】VS2019 使用C/C++ 生成DLL 文件,并用 C/C++、C#调用DLL


前言

在C#开发软件的过程中,要经常调用C/C++生成的dll,本文主要介绍用C/C++生成dll的步骤,以及用C/C++、C#两种语言实现dll的引用实现。本文使用的IDE是VS2019,文章通过具体实例进行讲解,大家可以跟着自己动手进行测试。


一、生成dll

新建项目-C+±动态链接库(DLL)

在这里插入图片描述

项目-右键-属性-C/C+±预编译头:不使用预编译头。

在这里插入图片描述

项目-右键-属性-C/C+±高级:编译为:C。(也可以不更改,默认就好)

在这里插入图片描述

删除原有所有.c、.h文件,新建.c、.h文件

在这里插入图片描述

  • Mydll.c文件代码如下:
#include<stdio.h>
#include"Mydll.h"
void test_print(char const* str)
{
    printf("测试输出的内容是:%s\n", str);
}

int test_sum(int a, int b)
{
    return a + b;
}

  • Mydll.h文件代码如下:
#include<stdio.h>

_declspec(dllexport) void test_print(char const* str);
_declspec(dllexport) int test_sum(int a, int b);

特别说明:
在这里插入图片描述
如果上图写错的话,则在depends.exe或dumpbin.exe(VS自带)中无法查看C/C++生成的DLL中的函数

dumpbin.exe的使用方法:
dumpbin.exe路径:【C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Tools\MSVC\14.16.27023\bin\Hostx86\x86】(说明:不同版本的VS,只需更改2017为相应版本号)

定位到上述的路径,然后在文件路径中输入cmd, 定位到路径下。
执行命令:dumpbin.exe -exports “xxx.dll”(dll的路径)

depends.exe下查找dll的函数名:
使用depends.exe打开一个dll文件【注:下图中打开的文件是C/C++随便生成的dll,不要看!】
在这里插入图片描述

  • 生成.dll和.lib文件:
    在这里插入图片描述
    在这里插入图片描述

二、C/C++调用dll

将生成的DLL文件拷贝到项目目录的Debug下

在这里插入图片描述
在这里插入图片描述

项目右键-属性-VC++目录-库目录-将.dll和.lib所在文件夹目录写入库目录中

项目-资源文件右键添加现有项-将.lib添加进去 或者 直接#pragma comment(lib,“Dll1.lib”)(本方法可省略此步)

C++源代码:

需要使用三个函数:LoadLibraryA,GetProcAddressFreeLibrary

#include <stdlib.h>
#include <windows.h>
#include<stdio.h>

int main(int argc, char const* argv[])
{
	void(*test_print)(char const*) = NULL;
	int(*test_sum)(int, int) = NULL;

	HMODULE module = LoadLibraryA("Dll1.dll");
	if (module == NULL)
	{
		system("error load");
	}

	test_print = (void(*)(char const*))GetProcAddress(module, "test_print");
	test_sum = (int(*)(int, int))GetProcAddress(module, "test_sum");

	if (test_print != NULL)
	{
		test_print("输出测试");
	}
	else 
	{
		system("function p_test_print can not excute");
	}

	int sum_result;
	if (test_sum != NULL)
	{
		sum_result = test_sum(234, 432);
		printf("求和结果是:%d\n", sum_result);
	}
	else 
	{
		system("function p_test_print can not excute");
	}
	FreeLibrary(module);
	system("pause");
	return 0;
}

运行结果:

在这里插入图片描述

三、C#调用dll

将生成的DLL文件拷贝到C#项目目录的Debug下

在这里插入图片描述

C#源代码:

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

/*引入C/C++生成的dll时需要添加*/
using System.Runtime.InteropServices;

namespace ConsoleApp2
{
    class Program
    {
        [DllImport("Dll1.dll", EntryPoint = "test_sum", CallingConvention = CallingConvention.Cdecl)]
        public static extern int test_sum(int a, int b);

        static void Main(string[] args)
        {
            int a = 234, b = 432;
            int sum = 0;
            Console.WriteLine("{0}+{1}={2}", a, b, test_sum(a, b));
            Console.ReadKey();
        }
    }
}

在这里插入图片描述

运行结果:

在这里插入图片描述

补充:

.lib和.dll的区别

引用网上的资料:

(1)lib是编译时需要的,dll是运行时需要的
如果要完成源代码的编译,有lib就够了。
如果要使动态连接的程序运行起来,有dll就够了。
在开发和调试阶段,当然最好都有。

(2)一般的动态库程序有lib文件和dll文件。lib文件是必须在编译期就连接到应用程序中的,而dll文件是运行期才会被调用的。**如果有dll文件,那么对应的lib文件一般是一些索引信息,具体的实现在dll文件中。**如果只有lib文件,那么这个lib文件是静态编译出来的,索引和实现都在其中。静态编译的lib文件有好处:给用户安装时就不需要再挂动态库了。但也有缺点,就是导致应用程序比较大,而且失去了动态库的灵活性,在版本升级时,同时要发布新的应用程序才行。

(3)在动态库的情况下,有两个文件,一个是引入库(.LIB)文件,一个是DLL文件,引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行时再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。从上面的说明可以看出,DLL文件必须随应用程序一起发行,否则应用程序将会产生错误。

调用DLL

引入dll的方法:

1、LoadLibray 一般是动态加载DLL时(不需要对应的头文件和LIB)。动态调用方式是由编程者用API函数加载和卸载DLL来达到调用DLL的目的,使用上较为复杂,但是能更加有效的使用内存,是编制大型应用程序时的重要方式。(本文采用)

2、#pragma comment 一般是静态加载DLL时(对应的头文件、DLL和LIB缺一不可,并且生产的EXE没有找到DLL文件就会导致“应用程序初始化失败”)。静态调用方式由编译系统完成对DLL的加载和应用程序时DLL卸载的编码,简单实用但不灵活

3、#import指令用于从一个类型库中结合信息。该类型库的内容被转换为C++类,主要用于描述COM界面。

总结

以上就是关于用C/C++ 生成dll,并用C/C++和C#调用dll的学习,希望对大家有帮助。

本文源码链接

https://download.csdn.net/download/sinat_40003796/85202652

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-24 09:11:57  更:2022-04-24 09:13:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 21:16:48-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码