热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

visualstudio建立dll类型工程、控制台程序

这篇文章主要介绍了visualstudio建立dll、控制台类型工程的相关知识,感兴趣的朋友跟随脚本之家小编一起学习吧

1. vs工程类型相关知识

在使用vs创建工程时,如果在“模板”中选的是“Win32”,不管是“Win32控制台应用程序”、还是“Win32项目”,工程创建完成后,在“属性--C/C++--预处理器定义”中都会有宏定义:"WIN32",因此,可以在代码中通过检查是否有宏定义"WIN32"对代码做好windows和linux的控制;

在创建win32的工程时,不论是选择“Win32控制台应用程序”、还是“Win32项目”最终都会跳到”应用程序设置“向导,该向导中需要使用者选择”应用程序类型“,共包括四种:windows应用程序、控制台程序、DLL(D)、静态库(S)。只是起初如果选择的是“Win32控制台应用程序”这里vs将默认在此向导中把类型选择为”控制台应用程序“,如果起初选择的是“Win32项目”这里vs将默认在此向导中把类型选择为”控制台应用程序“windows应用程序”。当我们是要封装dll接口时,在这里要选择“Dll(D)”

在vs创建工程时,如果选择的应用类型是“DLL(D)”时,工程创建完成后,在“属性--C/C++--预处理器定义”中会定义:宏定义"WIN32"、“工程名称(大写字母)_EXPORTS”。

2. 创建dll类型工程的相关知识

在Dll类型的工程中,dll头文件中的宏定义如下:

1.// 下列 ifdef 块是创建使从 DLL 导出更简单的 
2.// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 ONEDLL_EXPORTS 
3.// 符号编译的。在使用此 DLL 的 
1.// 任何其他项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将 

// ONEDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的// 符号视为是被导出的。#ifdef ONEDLL_EXPORTS#define ONEDLL_API extern "C" __declspec(dllexport)#else#define ONEDLL_API extern "C" __declspec(dllimport)
#endif

__declspec(dllexport) 表示函数为DLL输出函数,即其他应用程序可以调用该函数

extern “C” __declspec(dllexport) int add(int a, int b);

其中 extern “C”为声明为C编译。由于C++编译器在编译的时候会造成其函数名的该变,在其他应用程序中导致函数不可调用,而C编译器则不会在编译后改变其函数名。这样如果用C编译的程序来调用该dll中的函数时,可能会造成找不到该函数。

__declspec(dllexport) __declspec(dllimport)一般是使用宏的形式

这样在DLL代码本身就是__declspec(dllexport) ,在使用DLL的程序中就变成了__declspec(dllimport),这两标志分别用来指明当前的函数将被导出,和当前函数是被导入的。

定义一个接口函数

1.ONEDLL_API int fnOneDll(void); 

3. dll的调用方式

   DLL的调用分为两种方式:动态和静态(显示动态链接和隐式动态链接)

 (1) 动态调用(显示动态链接):

 typedef int(*lpAddFun)(int, int); //宏定义函数指针类型
 lpAddFun add;//函数指针
 HINSTANCE hDll=LoadLibrary(“path”);
 add=(lpAddFun)GetProcAddress(hDll, "add");//获得dll中的add函数指针
 FreeLibrary(hDll);

在从dll调用中返回的函数、指针或者类都是以指针的方式的,即返回的是函数、变量或类的地址。这里一定要注意,不能简单的用函数名来赋值。

(2) 静态调用(隐式动态链接):

 将生成的.dll和.lib文件拷入到调用dll的工程中,用命令

 #pragma comment(lib,"dllTest.lib"),实现静态调用,即把该dll在编译的时候也编译到exe文件中去,而后在工程中调用时用下面的代码:
 #pragma comment(lib,"dllTest.lib")//.lib文件中仅仅是关于其对应DLL文件中函数的重定位信息
 extern "C" __declspec(dllimport) add(int x,int y);
 int main(int argc, char* argv[])
 {
  int result = add(2,3);
  printf("%d",result);
  return 0;
 }

   由上述代码可以看出,静态调用方式的顺利进行需要完成两个动作:

   (1) 告诉编译器与DLL相对应的.lib文件所在的路径及文件名,#pragma comment(lib,"dllTest.lib")就是起这个作用。程序员在建立一个DLL文件时,连接器会自动为其生成一个对应的.lib文件,该文件包含了DLL 导出函数的符号名及序号(并不含有实际的代码)。在应用程序里,.lib文件将作为DLL的替代文件参与编译。另外一种显式调用的方式是设置vc中的目录和includefiles来实现

   (2) 声明导入函数,extern "C" __declspec(dllimport) add(int x,int y)语句中的__declspec(dllimport)发挥这个作用。静态调用方式不再需要使用系统API来加载、卸载DLL以及获取DLL中导出函数的地址。这是因为,当程序员通过静态链接方式编译生成应用程序时,应用程序中调用的与.lib文件中导出符号相匹配的函数符号将进入到生成的EXE 文件中,.lib文件中所包含的与之对应的DLL文件的文件名也被编译器存储在EXE文件内部。当应用程序运行过程中需要加载DLL文件时,Windows将根据这些信息发现并加载DLL,然后通过符号名实现对DLL 函数的动态链接。这样,EXE将能直接通过函数名调用DLL的输出函数,就象调用程序内部的其他函数一样。

总结

以上所述是小编给大家介绍的visual studio 建立工程(dll、控制台程序)等,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!


推荐阅读
  • Skywalking系列博客1安装单机版 Skywalking的快速安装方法
    本文介绍了如何快速安装单机版的Skywalking,包括下载、环境需求和端口检查等步骤。同时提供了百度盘下载地址和查询端口是否被占用的命令。 ... [详细]
  • 本文是一位90后程序员分享的职业发展经验,从年薪3w到30w的薪资增长过程。文章回顾了自己的青春时光,包括与朋友一起玩DOTA的回忆,并附上了一段纪念DOTA青春的视频链接。作者还提到了一些与程序员相关的名词和团队,如Pis、蛛丝马迹、B神、LGD、EHOME等。通过分享自己的经验,作者希望能够给其他程序员提供一些职业发展的思路和启示。 ... [详细]
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 35岁程序员连续被2家公司裁掉,网友酸了,成功入职成事业编晒出福利
    这篇文章讲述了一个35岁程序员连续被两家公司裁掉的故事,他在遭遇中年危机后成功入职事业单位,并分享了入职后的福利。文章探讨了程序员在互联网行业中的竞争力下降的原因。 ... [详细]
  • 本文详细介绍了云服务器API接口的概念和作用,以及如何使用API接口管理云上资源和开发应用程序。通过创建实例API、调整实例配置API、关闭实例API和退还实例API等功能,可以实现云服务器的创建、配置修改和销毁等操作。对于想要学习云服务器API接口的人来说,本文提供了详细的入门指南和使用方法。如果想进一步了解相关知识或阅读更多相关文章,请关注编程笔记行业资讯频道。 ... [详细]
  • Linux磁盘的分区、格式化的观察和操作步骤
    本文介绍了如何观察Linux磁盘的分区状态,使用lsblk命令列出系统上的所有磁盘列表,并解释了列表中各个字段的含义。同时,还介绍了使用parted命令列出磁盘的分区表类型和分区信息的方法。在进行磁盘分区操作时,根据分区表类型选择使用fdisk或gdisk命令,并提供了具体的分区步骤。通过本文,读者可以了解到Linux磁盘分区和格式化的基本知识和操作步骤。 ... [详细]
  • 本文介绍了Linux系统中正则表达式的基础知识,包括正则表达式的简介、字符分类、普通字符和元字符的区别,以及在学习过程中需要注意的事项。同时提醒读者要注意正则表达式与通配符的区别,并给出了使用正则表达式时的一些建议。本文适合初学者了解Linux系统中的正则表达式,并提供了学习的参考资料。 ... [详细]
  • Ubuntu 9.04中安装谷歌Chromium浏览器及使用体验[图文]
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
author-avatar
Tong-david
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有