iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >P/Invoke之C#调用动态链接库DLL的方法是什么
  • 695
分享到

P/Invoke之C#调用动态链接库DLL的方法是什么

2023-07-05 19:07:54 695人浏览 安东尼
摘要

这篇文章主要介绍了P/Invoke之C#调用动态链接库DLL的方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇P/Invoke之C#调用动态链接库DLL的方法是什么文章都会有所收获,下面我们一起来看看吧

这篇文章主要介绍了P/Invoke之C#调用动态链接库DLL的方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇P/Invoke之C#调用动态链接库DLL的方法是什么文章都会有所收获,下面我们一起来看看吧。

    P/Invok是什么?

    本编所涉及到的工具以及框架

    Visual Studio 2022

    .NET 6.0

    P/Invoke全称为PlatfORM Invoke(平台调用),其实际上就是一种函数调用机制,通过P/Invoke就可以实现调用非托管Dll中的函数。

    在开始之前,我们首先需要了解C#中有关托管与非托管的区别

    托管(Collocation),即在程序运行时会自动释放内存;

    非托管,即在程序运行时不会自动释放内存。

    废话不多说,直接实操

    第一步:

    • 打开VS2022,新建一个C#控制台应用

    P/Invoke之C#调用动态链接库DLL的方法是什么

    • 右击解决方案,添加一个新建项,新建一个"动态链接库(DLL)",新建完之后需要右击当前项目--> 属性 --> C/C++ --> 预编译头 --> 选择"不使用编译头"

    P/Invoke之C#调用动态链接库DLL的方法是什么

    在新建的DLL中我们新建一个头文件,用于编写我们的方法定义,然后再次新建一个c++文件,后缀以.c 结尾

    P/Invoke之C#调用动态链接库DLL的方法是什么

    第二步:

    在我们DLL中的头文件(Native.h)中定义相关的Test方法,具体代码如下:

    #pragma once// 定义一些宏#ifdef __cplusplus#define EXTERN extern "C"#else#define EXTERN#endif#define CallinGConvention _cdecl// 判断用户是否有输入,从而定义区分使用dllimport还是dllexport#ifdef DLL_IMPORT #define HEAD EXTERN __declspec(dllimport)#else#define  HEAD EXTERN __declspec(dllexport)#endifHEAD int CallingConvention Sum(int a, int b);

    之后需要去实现头文件中的方法,在Native.c中实现,具体实现如下:

    #include "Native.h" // 导入头部文件#include "stdio.h"HEAD int Add(int a, int b){    return a+b;}
    • 在这些步骤做完后,可以尝试生成解决方案,检查是否报错,没有报错之后,将进入项目文件中,检查是否生成DLL (../x64/Debug)

    P/Invoke之C#调用动态链接库DLL的方法是什么

    第三步:

    在这里之后,就可以在C#中去尝试调用刚刚所声明的方法,以便验证是否调用DLL成功,其具体实现如下:

    using System.Runtime.InteropServices;class Program{    [DllImport(@"C:\My_project\C#_Call_C\CSharp_P_Invoke_Dll\x64\Debug\NativeDll.dll")]    public static extern int Add(int a, int b);    public static void Main(string[] args)    {        int sum = Add(23, 45);        Console.WriteLine(sum);        Console.ReadKey();    }}

    运行结果为:68,证明我们成功调用了DLL动态链库

    C#中通过P/Invoke调用DLL动态链库的流程

      通过上述一个简单的例子,我们大致了解到了在C#中通过P/Invoke调用DLL动态链库的流程,接下我们将对C#中的代码块做一些改动,便于维护

    在改动中我们将用到NativeLibrary类中的一个方法,用于设置回调,解析从程序集进行的本机库导入,并实现通过设置DLL的相对路径进行加载,其方法如下:

    public static void SetDllImportResolver (System.Reflection.Assembly assembly, System.Runtime.InteropServices.DllImportResolver resolver);

    在使用这个方法前,先查看一下其参数

    a、assembly: 主要是获取包含当前正在执行的代码的程序集(不过多讲解)
    b、resolber: 此参数是我们要注重实现的,我们可以通过查看他的元代码,发现其实现的是一个委托,因此我们对其进行实现。
    原始方法如下:

    public delegate IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath);

    实现resolver方法:

    const string NativeLib = "NativeDll.dll";static IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath){    string dll = Path.Combine(new DirectoryInfo(Environment.CurrentDirectory).Parent.Parent.Parent.Parent.ToString(), "x64","Release", "NativeDll.dll"); // 此处为Dll的路径    //Console.WriteLine(dll);    return libraryName switch    {        NativeLib => NativeLibrary.Load(dll, assembly, searchPath),        _ => IntPtr.Zero    };}

    该方法主要是用于区分在加载DLL时不一定只能是设置绝对路径,也可以使用相对路径对其加载,本区域代码是通过使用委托去实现加载相对路径对其DLL加载,这样做的好处是,便于以后需要更改DLL的路径时,只需要在这个方法中对其相对路径进行修改即可。

    更新C#中的代码,其代码如下:

    using System.Reflection;using System.Runtime.InteropServices;class Program{    const string NativeLib = "NativeDll.dll";    [DllImport(NativeLib)]    public static extern int Add(int a, int b);    static IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)    {        string dll = Path.Combine(new DirectoryInfo(Environment.CurrentDirectory).Parent.Parent.Parent.Parent.ToString(), "x64","Release", "NativeDll.dll");        Console.WriteLine(dll);        return libraryName switch        {            NativeLib => NativeLibrary.Load(dll, assembly, searchPath),            _ => IntPtr.Zero        };    }    public static void Main(string[] args)    {        NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), DllImportResolver);        int sum = Add(23, 45);        Console.WriteLine(sum);        Console.ReadKey();    }}

    最后重新编译,检查其是否能顺利编译通过,最终我们的到的结果为:68

    至此,我们就完成了一个简单的C#调用动态链接库的案例

      下面将通过一个具体实例,讲述为什么要这样做?(本实例通过从性能方面进行对比)

    在DLL中的头文件中,加入如下代码:

    HEAD void CBubbleSort(int* array, int length);

    在.c文件中加入如下代码:

    HEAD void CBubbleSort(int* array, int length){    int temp = 0;    for (int i = 0; i < length; i++)    {        for (int j = i + 1; j < length; j++)        {            if (array[i] > array[j])            {                temp = array[i];                array[i] = array[j];                array[j] = temp;            }        }    }}

    C#中的代码修改:

    using System.Diagnostics;using System.Reflection;using System.Runtime.InteropServices;class Program{    const string NativeLib = "NativeDll.dll";    [DllImport(NativeLib)]    public unsafe static extern void CBubbleSort(int* arr, int length);    static IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)    {        string dll = Path.Combine(new DirectoryInfo(Environment.CurrentDirectory).Parent.Parent.Parent.Parent.ToString(), "x64", "Release", "NativeDll.dll");        //Console.WriteLine(dll);        return libraryName switch        {            NativeLib => NativeLibrary.Load(dll, assembly, searchPath),            _ => IntPtr.Zero        };    }    public unsafe static void Main(string[] args)    {        int num = 1000;        int[] arr = new int[num];        int[] cSharpResult = new int[num];        //随机生成num数量个(0-10000)的数字        Random random = new Random();        for (int i = 0; i < arr.Length; i++)        {            arr[i] = random.Next(10000);        }        //利用冒泡排序对其数组进行排序        Stopwatch sw = Stopwatch.StartNew();        Array.Copy(arr, cSharpResult, arr.Length);        cSharpResult = BubbleSort(cSharpResult);        Console.WriteLine($"\n C#实现排序所耗时:{sw.ElapsedMilliseconds}ms\n");        // 调用Dll中的冒泡排序算法        NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), DllImportResolver);        fixed (int* ptr = &arr[0])        {            sw.Restart();            CBubbleSort(ptr, arr.Length);        }        Console.WriteLine($"\n C实现排序所耗时:{sw.ElapsedMilliseconds}ms");        Console.ReadKey();    }    //冒泡排序算法    public static int[] BubbleSort(int[] array)    {        int temp = 0;        for (int i = 0; i < array.Length; i++)        {            for (int j = i + 1; j < array.Length; j++)            {                if (array[i] > array[j])                {                    temp = array[i];                    array[i] = array[j];                    array[j] = temp;                }            }        }        return array;    }}

    执行结果:

    C#实现排序所耗时: 130ms
    C实现排序所耗时:3ms

    关于“P/Invoke之C#调用动态链接库DLL的方法是什么”这篇文章的内容就介绍到这里,感谢各位的阅读!相信大家对“P/Invoke之C#调用动态链接库DLL的方法是什么”知识都有一定的了解,大家如果还想学习更多知识,欢迎关注编程网精选频道。

    --结束END--

    本文标题: P/Invoke之C#调用动态链接库DLL的方法是什么

    本文链接: https://www.lsjlt.com/news/354623.html(转载时请注明来源链接)

    有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

    本篇文章演示代码以及资料文档资料下载

    下载Word文档到电脑,方便收藏和打印~

    下载Word文档
    猜你喜欢
    • P/Invoke之C#调用动态链接库DLL的方法是什么
      这篇文章主要介绍了P/Invoke之C#调用动态链接库DLL的方法是什么的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇P/Invoke之C#调用动态链接库DLL的方法是什么文章都会有所收获,下面我们一起来看看吧...
      99+
      2023-07-05
    • C++调用动态库和Python调用C++动态库的方法是什么
      这篇文章主要介绍“C++调用动态库和Python调用C++动态库的方法是什么”,在日常操作中,相信很多人在C++调用动态库和Python调用C++动态库的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答...
      99+
      2023-07-05
    • Qt之调用C#的动态库的解决方法
      环境:VS2019+Qt5.12 1. CLR库安装         首先,如果你VS2019没有安装...
      99+
      2024-04-02
    • linux动态链接库的使用方法
      这篇文章主要介绍“linux动态链接库的使用方法”,在日常操作中,相信很多人在linux动态链接库的使用方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”linux动态链接库的使用方法”的疑惑有所帮助!接下来...
      99+
      2023-06-09
    • android调用JNI SO动态库的方法是什么
      这篇文章主要介绍“android调用JNI SO动态库的方法是什么”,在日常操作中,相信很多人在android调用JNI SO动态库的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”android调用...
      99+
      2023-06-25
    • 详解VS2010实现创建并生成动态链接库dll的方法
      目录1、目的2、新建动态链接库3、添加导出类,并修改项目配置4、修改项目配置5、编译生成6、测试项目1、目的 在某些应用程序场景下,需要将一些类或者方法编译成动态链接库dll,以便别...
      99+
      2022-12-21
      VS创建生成动态链接库dll VS 动态链接库 VS dll
    • C#调用C++动态库接口函数和回调函数方法
      目录1. 前言2. 普通接口函数调用示例2.1 C++端编写接口2.2 C#端调用3. 回调函数调用示例3.1 C++端编写接口3.2 C#端调用1. 前言 需求: 当前C已经写好了...
      99+
      2024-04-02
    • 怎么使用C/C++生成的动态链接库
      这篇文章主要讲解了“怎么使用C/C++生成的动态链接库”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用C/C++生成的动态链接库”吧!操作环境:Visual Studio 2017.N...
      99+
      2023-06-26
    • Golang动态调用方法是什么
      Golang动态调用方法是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。main.gopackage main import ...
      99+
      2023-06-22
    • C#跨平台开发之使用C/C++生成的动态链接库
      操作环境:Visual Studio 2017 如何实现 使用 C# 进行嵌入式开发? .NET Core 虽然实现了跨平台,但是不可能处处使用 C# 开发,就好像没人使用SQL开发...
      99+
      2024-04-02
    • c语言生成动态库的方法是什么
      在C语言中,生成动态库的方法一般是通过编译链接的方式来实现的。下面是一般的步骤: 编写源代码文件:首先编写需要生成动态库的源代码...
      99+
      2024-03-02
      c语言
    • python调用c++动态库dll时的参数传递问题怎么解决
      本篇内容介绍了“python调用c++动态库dll时的参数传递问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!stringC++生...
      99+
      2023-06-29
    • spring职责链动态配置的方法是什么
      在Spring中,可以使用HandlerInterceptor接口来实现职责链的动态配置。 要配置动态的职责链,需要完成以下步骤: ...
      99+
      2024-02-29
      spring
    • Rust应用调用C语言动态库的操作方法
      目录外部功能接口FFIUDP套接字的读超时Rust调用C语言动态库中的函数避免重复造轮子,使用Rust官方C语言库外部功能接口FFI 虽然高级(脚本)编程语言的功能丰富,表达能力强,...
      99+
      2023-01-29
      Rust调用C语言动态库 Rust C语言动态库
    • makefile静态库连接的方法是什么
      在Makefile中,连接静态库的方法是使用`-l`标志指定要连接的静态库的名称,然后使用`-L`标志指定静态库文件所在的目录。以下...
      99+
      2023-09-08
      makefile
    • C#调用Dll传递字符串指针参数的方法是什么
      本篇内容主要讲解“C#调用Dll传递字符串指针参数的方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#调用Dll传递字符串指针参数的方法是什么”吧!最近用c#写一个小软件,要调用VC写...
      99+
      2023-06-26
    • java调用c语言接口的方法是什么
      Java调用C语言接口的方法主要有以下几种:1. 使用Java Native Interface(JNI):JNI是Java提供的一...
      99+
      2023-08-08
      java c语言
    • linux动态调整cpu频率的方法是什么
      在Linux中,可以使用以下方法动态调整CPU频率:1. 使用cpufreq工具:Linux提供了cpufreq工具集,可以用于管理...
      99+
      2023-09-08
      linux
    • MyBatis中动态SQL拼接的方法是什么
      MyBatis中动态SQL拼接的方法主要是使用if、choose、when、otherwise等标签来实现动态条件拼接。具体来说,可...
      99+
      2024-04-08
      MyBatis
    • C调用C++代码的方法是什么
      这篇文章主要介绍“C调用C++代码的方法是什么”,在日常操作中,相信很多人在C调用C++代码的方法是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C调用C++代码的方法是什么”的疑惑有所帮助!接下来,请跟...
      99+
      2023-06-25
    软考高级职称资格查询
    编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
    • 官方手机版

    • 微信公众号

    • 商务合作