C 调用 dll 文件

C 调用 dll 文件一 先使用 C 来创建一个 dll 文件 1 创建新项目 CreateDll012 选择 动态链接库 dll 文件 3 在 CreateDll01 cpp 源文件中添加如下代码 CreateDll01 cpp 定义 DLL 应用程序的导出函数 include stdafx h extern C declspec dllex

一、先使用C++来创建一个 .dll 文件

1、创建新项目:CreateDll01

 C 调用 dll 文件

2、选择 “动态链接库(.dll)” 文件

 C 调用 dll 文件

3、在 CreateDll01.cpp 源文件中添加如下代码

 C 调用 dll 文件

// CreateDll01.cpp : 定义 DLL 应用程序的导出函数。 // #include "stdafx.h" extern "C" __declspec(dllexport) int TheAdd(int a, int b) { return a + b; } extern "C" __declspec(dllexport) int TheSub(int c, int d) { return c - d; }

【注意】:

  • __declspec(dllexport)  表示这个函数需要导出到 dll 中供其他程序调用。
  • extern "C"  表示以C的格式进行导出(方便用C++以外的语言进行调用)。

4、生成解决方案,来将其编译成对应的 dll 文件, dll 文件位于该项目的 Debug 目录中

  C 调用 dll 文件

   C 调用 dll 文件

 


二、C#对 .dll 文件的调用介绍

1、每种编程语言调用DLL的方法都不尽相同。在C#调用DLL中,首先需要了解什么是托管,什么是非托管。一般可以认为:非托管代码主要是基于win 32平台开发的DLL,activeX的组件,托管代码是基于.net平台开发的。

2、C#调用 DLL 非托管代码的方法:

(1)、应该在C#语言源程序中声明外部方法,其基本形式如下:

[DLLImport(“DLL文件名”)] 修饰符 extern 返回变量类型 方法名称 (参数列表) eg: [DllImport("CreateDll01.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int TheAdd(int a, int b); 

(2)、用法总结

DLL文件名:要调用的外部库文件名或该文件路径,其中包含待调用的方法。
修饰符: 访问修饰符,除了abstract 以外在声明方法时可以使用的修饰符。
返回变量类型:要和 DLL文件中你需调用方法的返回值类型相同。
方法名称:在DLL文件中你需调用方法的名称(注意:该方法名称可以与 dll 文件中待调用的方法名称不同,此时需要在 DllImport() 中加上 EntryPoint 属性,让其值为DLL文件中你需调用方法的名称。相当于告诉该调用的函数入口点,然后就可以在下面的“方法名称 ”处重载该方法。若在   DllImport() 中没有 EntryPoint 属性,则需要调用的 “方法名称 ” 必须与 dll 文件中的函数名称相同 )
参数列表:在DLL文件中你需调用方法的列表。
注意:必需要在程序声明中使用 System.Runtime.InteropServices 命名空间。
DllImport只能放置在方法声明上。
DLL文件必须位于程序当前目录或系统定义的查询路径中(需要将生成的 DLL文件拷贝到当前程序的 bin\Debug 目录下)。
返回变量类型、参数列表一定要与DLL文件中的定义相一致。







DllImportAttribute 常用属性说明(详解):

CallingConvention:指定用于传递方法参数的调用约定。 默认值为 WinAPI,该值对应于基于 32 位 Intel 的平台的 __stdcall。

EntryPoint: 指定要调用 DLL 方法入口点。


三、C# 调用 .dll 文件的实例

1、创建一个新的控制台应用(.NET Framwork):CallTheDll01 . 注意:不能选择 “控制台应用(.NET Core)” ,选择该项时总是提示无法加载dll文件,使得调用 dll 文件失败。可能是由于“ 控制台应用(.NET Core)” 在VS中编译后默认无法生成 .exe 文件导致。

C 调用 dll 文件

2、接下来在C#的Program.cs 文件中的代码会有两种引入 DLL 文件的方式:

   引入方式一:拷贝 dll 文件到当前项目目录下,以 dll 文件名引入该文件

(1)、该方式必须将之前用C++编译的 dll 文件复制到控制台应用的 bin\Debug 目录下,否则会提示错误

 C 调用 dll 文件

(2)、在 Program.cs 文件中添加以下代码:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; namespace CallTheDll01 { class Program { // 必须要有 CallingConvention.Cdecl,否则程序会报错 [DllImport("CreateDll01.dll", CallingConvention = CallingConvention.Cdecl)] public static extern int TheAdd(int a, int b); // 若要让本程序中调用的函数名与DLL中的函数名不同,则需要在 DllImport()中添加 EntryPoint 属性 // 同时 EntryPoint 属性值必须与DLL中被调函数的名称相同,以告诉该调用函数的入口位置 [DllImport("CreateDll01.dll",EntryPoint ="TheSub", CallingConvention = CallingConvention.Cdecl)] public static extern int TestTheSub(int c, int d); //此时将被调函数的名称由TheSub重载为TestTheSub即可 static void Main(string[] args) { Console.WriteLine("The answer of 2+8 = {0}", TheAdd(2, 8)); Console.WriteLine("The answer of 8-2 = {0}", TestTheSub(8, 2)); Console.ReadKey(); } } } 

 引入方式二:通过 dll 文件的绝对路径来将该 dll 文件引入到控制台应用中*

(1)、通过绝对路径的方式,不需要将待调用的 dll 文件复制到当前控制台应用中。只需要给出该 dll 文件的绝对路径即可。使用该方式来引入 dll 文件非常方便修改和使用。

(2)、在 Program.cs 文件中添加以下代码:

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.InteropServices; namespace CallTheDll01 { class Program { // 在此处使用 CreateDll01.dll 文件的绝对路径 [DllImport(@"E:\Coding\C++\TheDLL\CreateDll01\Debug\CreateDll01.dll",CallingConvention=CallingConvention.Cdecl)] public static extern int TheAdd(int a, int b); // 由于上面已经使用了 CreateDll01.dll 文件的绝对路径,并且在下面的TheAdd(2, 8)处调用过该dll文件中的函数,所以 // 在此处可以只写该 dll文件名,但为了保险起见,还是最好写待调用dll文件的绝对路径名 [DllImport("CreateDll01.dll", EntryPoint = "TheSub",CallingConvention =CallingConvention.Cdecl)] public static extern int TestTheSub(int c, int d); static void Main(string[] args) { Console.WriteLine("The answer of 2+8 = {0}", TheAdd(2, 8)); Console.WriteLine("The answer of 8-2 = {0}", TestTheSub(8, 2)); Console.ReadKey(); } } }

3、点击 F5 运行结果如下:

   C 调用 dll 文件

4、总结、注意:

  • 如果C# 调用的 DLL 文件是通过模块(.def)的方式来创建的(方法二:使用模块(.def)的方式来进行生成 .dll 文件),则可以在 .def 文件中的 EXPORTS 输出的函数名后面 @n,来指定各个函数的序号,以使其调用时让 EntryPoint 属性值用该序号来代替相应的函数名。如:[DllImport(“CreateDll01.dll” , EntryPoint =”#2″ , CallingConvention = CallingConvention.Cdecl)]

参考资料:

[1]  在C#中调用和调试C++代码

[2]  C# 调用外部dll

[3]  C#托管代码与C++非托管代码互相调用一

[4]  C# 中调用dll

[5]  利用C++创建DLL并C#调用

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233833.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 安排工作任务五步法[通俗易懂]

    安排工作任务五步法[通俗易懂]安排工作五步法第一回,讲清楚具体事项;验收标准,工作内容是什么,方法第二回,让员工原封不动地复述事项;让执行者重复一遍要求做的这项工作内容,一定要让他说清楚,有点含糊都要马上纠正第三回,和员工讨论该事项的目的;重要性、影响面第四回,交流并作出该事项的预案;假如在工作中遇到某某情况,问他会如何处理第五回,让员工围绕该事项阐明自身观点。让执行工作的人试试,如果是主导这项工作,他会如何来安排处理。看看他的逻辑,在结合自己,是否有值得改善的地方。也可以…

    2025年7月7日
    0
  • 贝塞尔方程与贝塞尔函数学习笔记

    贝塞尔方程与贝塞尔函数学习笔记《数学物理方法(顾樵)》第13章学习笔记第一节几个微分方程的引入三维波动方程:∂2v∂t2=a2(∂2v∂x2+∂2v∂y2+∂2v∂z2)≡a2∇2v\frac{\partial^2v}{\partialt^2}=a^2(\frac{\partial^2v}{\partialx^2}+\frac{\partial^2v}{\partialy^2}+\frac{\partial^2v}{\partialz^2})\equiva^2\nabla^2v∂t2.

    2025年7月24日
    0
  • ubuntu 7.04 ‘s sources list

    ubuntu 7.04 ‘s sources list

    2021年5月1日
    87
  • Wireshark过滤规则的使用!「建议收藏」

    Wireshark过滤规则的使用!「建议收藏」文章目录MAC地址过滤显示包含的MAC地址只显示源MAC地址只显示目标MAC地址IP地址过滤显示包含的IP地址只显示源IP地址只显示目标IP地址端口号过滤显示包含端口号为80的报文只显示源端口号为80的报文只显示目标端口号为80的报文过滤高层协议语法MAC地址过滤显示包含的MAC地址eth.addr==38:b1:db:d4:41:c5不管是源MAC地址还是目标MAC地址,只要包含38:b1:db:d4:41:c5的MAC地址都会显示出来只显示源MAC地址eth.src==38:b1:

    2022年7月13日
    22
  • Pycharm中将pyinstaller加入External Tools

    Pycharm中将pyinstaller加入External ToolsPycharm:2017.1.2PyInstaller:3.3.1第一步:安装pyinstaller网上有很多种方法,在此不赘述。pycharm中,安装很方便。进入设置(command+,)第二步:配置PyinstallerEXE依然是在设置中保存好。然后在pycharm上方tools中查看:我们点击这个功能,查看是否…

    2022年10月24日
    0
  • api header_apipost接口测试

    api header_apipost接口测试使用apipost进行接口测试的时候,有时候会用到一些自定义或者不常见的content-type格式,这个时候就要手动在header头部自定义content-type。这里我们自定义一个content-type,格式为application/octet-stream然后body选择的为form-data,然后什么body中什么都不填写,点击发送,发送的content-type的格式是为自定义的application/octet-stream。在body中添加参数进行发送,结果content-typ

    2022年8月24日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号