在第三章的基础上,接着添加一个显示调用项目

显示调用项目创建:

1.给解决方案添加一个新的控制台项目DisplayCall用于测试动态库,创建完成后设置为启动项目

2.DisplayCall.cpp添加相关代码 1 // DisplayCall.cpp : 定义控制台应用程序的入口点。

 //

 #include "stdafx.h"
#include <windows.h> //需要包含windows.h typedef int(*PFUNC_MathSub)(int,int); //定义函数指针 int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hmdll = ::LoadLibrary(_T("../Debug/DynamicLibrary.dll"));//动态加载dll
if(!hmdll)
{
printf("LoadDll is fail");
}else
{
//获取动态库中的sub函数地址,强制类型转换为函数指针
PFUNC_MathSub pfMathSub = (PFUNC_MathSub)::GetProcAddress(hmdll,"MathSub");
int nResult = pfMathSub(,); //通过函数指针进行调用
printf("5 - 3 = %d",nResult);
21     ::FreeLibrary(hmdll);
}
getchar();
return ;
}

3.编译运行DisplayCall,结果发现出现异常?

4. 点击中断发现断在第19行,鼠标移到pfMathSub发现它的值为0. 说明没有获取到MathSub函数地址

打开动态库的头文件进行查看是不是输错函数名字了?函数名正确...

5. 真正导致bug产生的原因在于,C++函数编译时产生的函数名称与代码中实际函数名是不一样的

这里动态库项目采用的是c++, 那它生成时就是按C++编译方式生成函数名

这里可以使用depends来查看下dll信息,可是vs2012工具里尽然没有,那就只能借用第三方工具了

原始c++函数:int MathSub(int a ,int b) 编译后函数名称:?MathSub@@YAHHH@Z

c++函数名称都是以?开头,后面跟上函数名,然后@@YA代表的是c++默认调用方式__cdecl,

后面二个H代表是参数型是int型,返回值是int型,最后以@z代表结尾

6. 为了测试是否正确,修改代码, 把GetProcAddress第二个参数函数名改为?MathSub@@YAHHH@Z

F5运行,发现能成功调用MathSub函数了

7. 如果每次调用动态库中的函数都使用这种方式太过于复杂,于是忽另外一种简单的方式应运而生

修改动态库头文件,在函数最前面加上extern "C", 告诉编译器不要使用默认的C++方式编译,

该为使用C语言方式编译. 最后重新编译下动态库工程

8. 回到DisplayCall.cpp中,把代码改回来. 然后F5运行,发现异常信息消失了

9. 最后再用工具看一下用extern "C" 修饰的函数编译出来的函数名变成什么样了?

C语言方式编译出来函数名是MathSub, 这样我们就可以很方便的使用GetProcAddress获取函数地址了

总结:

如果需要显示调用动态库,尽量在导出函数前面加上extern "C"

而当使用第三方动态库,去GetProcAddress函数地址发现获取不到函数地址时,

可以尝试用工具去查看导出函数,以确定函数名称,以及查看相关的调用约定

VC 静态库与动态库(四)动态库创建与使用_显示调用的更多相关文章

  1. VC 静态库与动态库(三)动态库创建与使用_隐式链接

    动态库分为二种,一种隐式链接,另一种显示调用.不论哪种动态库,本质都是运行时动态加载 隐式链接:程序运行时,由编译系统自动加载动态库,然后根据程序的引入表进行重定位,当程序退出时自动卸载动态库 显示调 ...

  2. 1.改变项目 动态库、静态库属性。 2.使用运行库 /MD、/MT、/LD说明

    /MD./MT./LD(使用运行库) 有关 C 运行库以及使用 /clr(公共语言运行时编译) 进行编译时要使用哪些库的更多信息,请参见 CRT 库功能. 传递给链接器的给定调用的所有模块都必须使用相 ...

  3. mingw qt(可以去掉mingwm10.dll、libgcc_s_dw2-1.dll、libstdc++-6.dll的依赖,mingw默认都是动态链接gcc的库而TDM是静态链接gcc库,tdm版本更好用。用aspack压缩没有问题。qt本身不使用异常处理)good

    原文地址:mingw qt作者:孙1东 不使用Qt SDK,使用mingw编译qt源代码所遇问题及解决方法: configure -fast -release -no-exceptions -no-r ...

  4. GifShot - 创建动态 GIF 的 JavaScript 库

    GifShot 是一个可以创建流媒体,视频或图像的 GIF 动画的 JavaScript 库.该库的客户端特性使其非常便携,易于集成到几乎任何网站.利用最先进的浏览器 API ,包括 WebRTC , ...

  5. 再探Linux动态链接 -- 关于动态库的基础知识

      在近一段时间里,由于多次参与相关专业软件Linux运行环境建设,深感有必要将这些知识理一理,供往后参考. 编译时和运行时 纵观程序编译整个过程,细分可分为编译(Compiling,指的是语言到平台 ...

  6. PHP 动态添加 Mcrypt 扩展库

    简介: PHP 动态添加 Mcrypt 扩展库,这是一个支持多种加密.解密算法.模式的扩展库. shell > php -m | grep mcrypt # 如果没有输出,就是缺少这个扩展 sh ...

  7. 再探Linux动态链接 -- 关于动态库的基础知识(Dynamic Linking on Linux Revisited)

      在近一段时间里,由于多次参与相关专业软件Linux运行环境建设,深感有必要将这些知识理一理,供往后参考. 编译时和运行时 纵观程序编译整个过程,细分可分为编译(Compiling,指的是语言到平台 ...

  8. GCC链接库的一个坑:动态库存在却提示未定义动态库的函数

    背景 在GCC中已经指定链接库,然而编译时却提示动态库函数未定义! 测试出现的错误提示如下: [GMPY@13:48 tmp]$gcc -o test -L. -lmylib test.c /tmp/ ...

  9. 动态代理的两种方式,以及区别(静态代理、JDK与CGLIB动态代理、AOP+IoC)

    Spring学习总结(二)——静态代理.JDK与CGLIB动态代理.AOP+IoC   目录 一.为什么需要代理模式 二.静态代理 三.动态代理,使用JDK内置的Proxy实现 四.动态代理,使用cg ...

随机推荐

  1. jQuery核心(一)

    API文档:http://jquery.cuishifeng.cn/ 一. jQuery.extend(object) 用于扩展jQuery对象本身.用来在jQuery命名空间上增加新函数. jQue ...

  2. git报错_you are not allowed to push code to protected branches on this project

    问题描述 今天在提交代码的时候,由于使用的是新库,写完代码后,进行push,发现报错 you are not allowed to push code to protected branches on ...

  3. Python tempfile (临时文件)

    Python tempfile 大量临时数据放在内存中会占用大量资源,可以使用临时文件来进行储存 临时文件不用命名,且使用后会被自动删除 TemporaryFile 使用 TemporaryFile ...

  4. Bliss OS 12.1下载 PC上Android10体验

    下载也不是一帆风顺啊 这是设计者的secret: https://forum.xda-developers.com/android/software/bliss-os-x86-pc-s-12-x-de ...

  5. Linux学习笔记-第10天 特殊的交换分区

    关键词,分区.mkswap swapon .uquota,RAID,/etc/fstab 此章开始,难度有些提升.不过还好自己有点基础.

  6. Avalon的小故事 (1)

    我:这个游戏真没意思,我为什么要玩这种东西 A:你渡过了前期才能发现这个游戏的乐趣 我:那我为什么不换一个游戏玩呢?换一个开头就让人欲罢不能的游戏? B:你这是逃避!你个懦夫! 我:我连自己选择游戏的 ...

  7. RocketMQ支持事务消息机制

    事务消费 我们经常支付宝转账余额宝,这是日常生活的一件普通小事,但是我们思考支付宝扣除转账的钱之后,如果系统挂掉怎么办,这时余额宝账户并没有增加相应的金额,数据就会出现不一致状况了. 上述场景在各个类 ...

  8. erlang 资源

    https://github.com/ninenines https://github.com/drobakowski https://github.com/dizzyd

  9. 《一起学netty》

    o文章摘自 netty 官网(netty.io)   netty 是一个异步的,事件驱动的网络应用通信框架,可以让我们快速编写可靠,高性能,高可扩展的服务端和客户端   样例一:discard ser ...

  10. Debug 路漫漫-13:Python: pandas IndexError: single positional indexer is out-of-bounds

    在数据预处理过程中,出现:IndexError: single positional indexer is out-of-bounds 原因是在使用 Pandas 读取 dataframe 的时候,分 ...