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

显示调用项目创建:

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. RPM 包

    RPM 包 RPM 包是由 Red Hat 公司所开发的包管理系统 RPM 经过编译,无法看到源码,但是安装速度会快很多 RPM 包管理 RPM 包命名规则 包名 - 版本号 - 发布版本号 . 软件 ...

  2. talk 64

    dGhpcyBpcyBhIGV4YW1wbGUKYmIxMjMxMjNACgoxNjMKCmFhMzA2MzA2

  3. Vue.js 创建第一个应用

    VUE官网下载Vue.js文件或者用Vue的CDN地址 在项目中引入Vue.js文件 代码: <!doctype html> <html lang="en"> ...

  4. A1063 Set Similarity (25 分)

    一.技术总结 这个题目是属于set容器的内容,使用可以减少很多代码量 开始试过在同一个for循环中定义两个auto,结果编译通不过,有时候构思很重要,就比如这一题,开始我是一个一个去加,而代码中是,先 ...

  5. Wireshark使用入门

    目录 1. Wireshark介绍 1.1 客户端界面 1.2 Display Filter 的常用方法 1.3 界面上一些小TIPS 2. 使用Wireshark分析TCP三次握手过程 2.1 三次 ...

  6. HTML连载17-id选择器&类选择器

    一.问题:我们前面讲了标签选择器有一个缺陷就是它不加选择的把所有相同的标签全都变成统一样式,这对于我们个性化定制产生了阻碍,因此我们便引出了id选择器,来进行特别指定进行配置样式 二.id选择器 1. ...

  7. PDF文件添加二维码水印教程

    maven配置iText的jar,主要不是所有私服都有iText的jar,maven仓库没有的,可以去https://mvnrepository.com/artifact/com.itextpdf/i ...

  8. C++回调,函数指针

    想要理解回调机制,先要理解函数指针 函数指针 函数指针指向的是函数而非对象,和其他指针一样,函数指针指向某种特定的类型 函数的类型由他的返回类型和参数类型共同决定,与函数名无关,如: bool len ...

  9. Vue内置组件[回顾]

    1.动态组件 在某些场景,往往需要我们动态切换页面部分区域的视图,这个时候内置组件component就显得尤为重要. component接收一个名为is的属性,is的值应为父组件中注册过的组件的名称, ...

  10. jQuery HTML/CSS 方法大全

    下表列出了用于操作HTML和CSS的所有方法. 方法 描述 addClass() 向所选元素添加一个或多个类名 after() 在所选元素之后插入内容 append() 在所选元素的末尾插入内容 ap ...