函数调用约定与函数名称修饰规则(三)
来源:互联网 发布:java中io与nio的差异 编辑:程序博客网 时间:2024/05/17 05:51
作者:星轨(oRbIt)
E_Mail:inte2000@163.com
转载请注明原作者,否则请勿转载
函数调用约定和名字修饰规则不匹配引起的常见问题
函数调用时如果出现堆栈异常,十有八九是由于函数调用约定不匹配引起的。比如动态链接库a有以下导出函数:
在了解了函数调用约定和函数的名修饰规则之后,再来看在C++程序中使用C语言编译的库时经常出现的LNK 2001错误就很简单了。还以上面例子的两个模块为例,这一次两个模块在编译的时候都采用__stdcall调用约定,但是a.dll使用C语言的语法编译的(C语言方式),所以a.dll的载入库a.lib中MakeFun函数的名字修饰就是“_MakeFun@4”。b包含了a提供的头文件中MakeFun函数声明,但是由于b采用的是C++语言编译,所以MakeFun在b模块中被按照C++的名字修饰规则命名为“?MakeFun@@YGJJ@Z”,编译过程相安无事,链接程序时c++的链接器就到a.lib中去找“?MakeFun@@YGJJ@Z”,但是a.lib中只有“_MakeFun@4”,没有“?MakeFun@@YGJJ@Z”,于是链接器就报告:
error LNK2001: unresolved external symbol ?MakeFun@@YGJJ@Z
解决的方法和简单,就是要让b模块知道这个函数是C语言编译的,extern "C"可以做到这一点。一个采用C语言编译的库应该考虑到使用这个库的程序可能是C++程序(使用C++编译器),所以在设计头文件时应该注意这一点。通常应该这样声明头文件:
这样C++的编译器就知道MakeFun的修饰名是“_MakeFun@4”,就不会有链接错误了。
许多人不明白,为什么我使用的编译器都是VC的编译器还会产生“error LNK2001”错误?其实,VC的编译器会根据源文件的扩展名选择编译方式,如果文件的扩展名是“.C”,编译器会采用C的语法编译,如果扩展名是“.cpp”,编译器会使用C++的语法编译程序,所以,最好的方法就是使用extern "C"。
- 函数调用约定与函数名称修饰规则(三)
- 函数调用约定与函数名称修饰规则(一)
- 函数调用约定与函数名称修饰规则(二)
- 函数调用约定与函数名称修饰规则(一)
- 函数调用约定与函数名称修饰规则
- 函数调用约定与函数名称修饰规则
- 函数调用约定与函数名称修饰规则
- 函数调用约定与函数名称修饰规则
- 函数调用约定与函数名称修饰规则
- 函数调用约定与函数名称修饰规则(举例)
- 函数调用约定与函数名称修饰规则(原理)
- 函数调用约定与函数名称修饰规则
- 函数调用约定与函数名称修饰规则--VC
- c++函数调用约定与函数名称修饰规则
- C/C++函数调用约定与函数名称修饰规则
- C/C++函数调用约定和函数名称修饰规则
- C/C++函数调用约定与函数名称修饰规则探讨
- C/C++函数调用约定与函数名称修饰规则探讨
- Pakistan: Low Stocks Ensure Cotton Prices Remains Stable
- China: EU Halts Accepting License Applications for Trouser Imports
- 函数调用约定与函数名称修饰规则(二)
- Belgium: EU Head Mandelson for Talk with China over Textile Violations
- 啃书
- 函数调用约定与函数名称修饰规则(三)
- 关于代码生成器
- Oracle自定义函数——f_henry_GetStringLength
- 程序员应该看的几本书
- 甄子丹!
- 简单的SQL Server数据库数据读取与数据操作
- So many things to learn, still.
- 菜鸟请教各位大侠: 我想学Java,要先学c/c++吗?菜鸟谦虚请教,谢谢各位前辈!(以前接触过vb6.0)
- 一个有用的SQL语句