DLL的Export和Import及extern "C"
今天使用Unrar.dll,在调用RARProcessFileW时,VS总是提示“error LNK2001: 无法解析的外部符号”。
Unrar.dll中是使用 extern "C" 对外输出函数,测试发现,其他函数可以正常调用,只有RARProcessFileW有此错误。
最后检查发现在.def文件中没有导出这个文件。
EXPORTS
RAROpenArchive
RAROpenArchiveEx
RARCloseArchive
RARReadHeader
RARReadHeaderEx
RARProcessFile
RARProcessFileW
RARSetCallback
RARSetChangeVolProc
RARSetProcessDataProc
RARSetPassword
RARGetDllVersion
DLL的import是指使用DLL的程式引入DLL中的函数和数据。
一般来讲,在DLL编程过程中,对于导出的函数前 都需要加入 extern “C”,
extern 表示这是个全局函数,可以供各个其他的函数调用;
“C” 表示编译时按照 C编译器的方式进行编译,而不是C++。 C++的编译方式考虑了函数重载,所以对函数名进行了新的修饰,产生了所谓的破坏性命名。
不过,也有特殊情况,有三种例外情况可以不加extern “C”:
1。如果不是用C++编译器而是用C编译DLL,名字不会变,可以不加extern "C"
2。如果DLL的使用者知道是用C++编译器编译DLL,不加extern “C”也可以,因为他知道名字改变的规则。调用GetProcAddress时,把函数名字改了就是了,改为修饰后的函数名。 如 fnDll1 改为 ?fnDll1@@YAHXZ。
例子关键代码如下:
----------------------------
DLL部分:
// This is an example of an exported function.
DLL1_API int __cdecl fnDll1(void)
{
return 42;
}
输出的修饰函数名为?fnDll1@@YAHXZ
DLL1_API int __cdecl fnDll1(int a)
{
return 42+a;
}
输出的修饰函数名为?fnDll1@@YAHH@Z
-----------------------------
EXE部分:
HINSTANCE hModule = LoadLibrary("dll1.dll");
ASSERT(hModule);
typedef int (*fnDll1)();
fnDll1 pfnDll1 = NULL;
//VERIFY(pfnDll1 = (fnDll1)::GetProcAddress(hModule, "fnDll1"));
VERIFY(pfnDll1 = (fnDll1)::GetProcAddress(hModule, "?fnDll1@@YAHXZ"));
ASSERT(pfnDll1() == 42);
typedef int (*fnDll2)(int);
fnDll2 pfnDll2 = NULL;
VERIFY(pfnDll2 = (fnDll2)::GetProcAddress(hModule, "?fnDll1@@YAHH@Z"));
ASSERT(pfnDll2(3) == 45);
---------------------------
3.上面的2太麻烦了。所以还有一种方法是使用def文件。
(如果DLL使用的是def文件,要删除TestDll.h文件中关键字extern "C",即2者是不能共存的)。
def 文件(模板定义文件),第一个语句必须是 LIBRARY 语句,指出DLL的名字;
EXPORTS语句 列出被导出函数的名字;将要输出的函数罗列出来,这个函数名字必须与定义函数的名字完全一致,如此既可以得到
一个没有任何修饰符的函数名了。
被导出的函数 可以和一个序号相对应。定义序号时必须在数字前加一个@。例如 isRUINIan @1 //IsRuiNian 函数对应序号为 1
这样的话,我们既可以GetProAddress(hinstance,“IsRuiNian”),也可以 GetProAddress(hinstance,(LPCSTR)1)实现调用。
DLL的Export和Import及extern "C"的更多相关文章
- export和import实现模块化
export和import实现模块化 阅读目录 ES6的模块化的基本规则或特点: 下面列出几种import和export的基本语法: ES6导入的模块都是属于引用: 循环依赖的问题: 浏览器兼容: 参 ...
- 【从翻译mos文章】不再用par file如果是,export or import 包含大写和小写表名称表
不再用par file如果是,export or import 包含大写和小写表名称表 参考原始: How to Export or Import Case Sensitive Tables With ...
- module.exports,exports,export和export default,import与require区别与联系【原创】
还在为module.exports.exports.export和export default,import和require区别与联系发愁吗,这一篇基本就够了! 一.首先搞清楚一个基本问题: modu ...
- ES6中的export以及import的使用多样性
模块功能主要由两个命令构成:export和import.export命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能. 一.export导出模块使用部分的几种方式 一个模块就是一 ...
- ES6模块之export和import详解
ES6中的模块即使一个包含JS代码的文件,在这个模块中所有的变量都是对其他模块不可见的,除非我们导出它.ES6的模块系统大致分为导出(export)和导入(import)两个模块. 1.模块导出(ex ...
- ES6 Module export与import复合使用
export与import复合使用 基本语法 export {...} from '文件'; 等价于 import {...} from "文件": export {...} 先加 ...
- export 和import使用
在JavaScript ES6中,export与export default均可用于导出常量.函数.文件.模块等,你可以在其它文件或模块中通过import+(常量 | 函数 | 文件 | 模块)名的方 ...
- export,import ,export default区别
export,import ,export default区别 一.export,import ,export default ES6模块主要有两个功能:export和import export用于对 ...
- export,import ,export default 彻底弄痛
ES6模块主要有两个功能:export和import 说白了就是一个淡出一个导入,就相当于以前的公共js样,哪个页面要用,就script 引入这个js ,然后 无耻的调用这个js中的方法了. ex ...
随机推荐
- Pandas中关于accessor的骚操作
来自:Python那些事 pandas中accessor功能很强大,可以将它理解为一种属性接口,通过它获得额外的方法. 下面用代码和实例理解一下: import pandas as pd pd.Ser ...
- “ORA-06550: 第 1 行, 第 7 列”解决方法
将本机能正常运行的维修生产日志代码发布到公司内测环境里无法正常运行,报错如下: execute() - pls–QuartzJob.java–quartzjob 开始执行! java.sql.SQLE ...
- 基于虹软sdk,java实现人脸识别(demo)
## 开发环境准备:###开发使用到的软件和工具:* Jdk8.mysql5.7.libarcsoft_face.dll(so).libarcsoft_face_engine.dll(so).liba ...
- Java se基础(类的属性及关键字)
public:说明该类的访问类型是公有的,它生成的对象能被其他的对象调用! abstract:用来声明抽象类! final;如果一个类被声明成final类型,那么就不能再由它派生出子类. 可以简单的看 ...
- spring aop通过注解实现日志记录
首先是几个概念:连接点(Joinpoint).切点(Pointcut).增强(Advice).切面(Aspect) 另外也要使用到注解. 需求:通过注解定义LogEnable.然后程序运行能够识别定义 ...
- Axure 元件焦点的控制
讲解如何控制光标的位置,主要学习了以下三种场景: 1.点击邮箱或者密码时,光标分别自动定位到email.password的文本框处: 2.还有将密码对应的文本框的内容设置为密码的格式(····) 3. ...
- ffmpeg 无损改变纵横比aspect
最后发觉, potplayer 里 Ctrl+Enter 或者 Enter 可以扩展到整个屏幕/保持比例,根本不需要额外去转换 如果整个视频都要改的话,把 -ss -t 参数去掉 ffmpeg -ss ...
- eclipse---->自己常用的快捷键
organize imports----> ctrl+shift+o 导入其他工程的类(在学习springboot的注解@EnableAutoConfiguration时用到) 关闭当前窗口的 ...
- WCF初见之SQL数据库的增删改查
1.首先要连接数据库,自然要有数据库啦,创建一个数据库表Login,并插入一个数据: --创建数据库表login CREATE TABLE Login ( UName VARCHAR(20) PRIM ...
- BGP-6,解决IBGP的水平分割