zz 关于external "C"的文章
2010-03-31 14:03
323 查看
EXTERNAL C的用法
2009-03-12 08:22:08
例:
两个文件:
c文件:C.c
cpp文件:CPP.cpp
在讨论extern "C"之前先来讨论extern。
1、C/C++里全局变量和全局函数的定义缺省是extern的。即如果一个project由好几个文件组成,那么在A文件的全局作用域中定义了全局变量或者全局函数,默认情况下在其他文件中是可见的,即其他的文件只要在自己的全局作用域中用extern显式声明A中的全局变量和函数,就可以使用A中定义的全局变量和全局函数。
2、需要注意的一点是,extern int external 这样的声明并不为external分配内存空间。这里只是一个声明,它告诉编译器 external 这个变量是在其他文件中定义。因此,在编译的时候即使找不到external的定义也不会报错,因为连接的时候会在其他文件的obj中找到external。
3、cout<<"the value of external in c file is: "<<external<<endl;
external=10;
cout<<"after modified in cpp is : "<<func()<<endl;
用这三句代码来说明extern:变量external是在C.c文件中定义的,CPP.cpp只是声明了一下,它告诉编译器CPP中用到的external是在别的文件中定义的。
首先,打印出external的值,为5(C文件中定义externl为5,这更加说明了CPP中并不为external开辟新空间,否则应该为0),
然后,在CPP文件中将external改为10,通过调用func()显式external的值。func()是C中的函数,它返回external的值,结果打印出10(进一步说明了external定义在C,使用在CPP)。
4、声明的时候,如果去掉变量前面的extern,将会出现连接错误,提示定义了两个同名变量。
5、与extern对应的是static。在全局作用域里用static显式声明的变量和函数说明它们只能供其所在的文件使用,其他文件对其不可见;如果是在模块中声明一个static变量,则这个变量的作用域还是所在模块,但是生命周期延长到程序结束。
再来看extern "C"
extern "C" 的引用就是为了解决C++语言和C语言的混合编程问题。
C++支持的函数重载机制导致了C和C++编译机制的不同。
1,比如对一个函数
void foo( int x, int y );
由C编译器编译后符号库中的名字为_foo;而C++编译器编译后则为_foo_int_int,称为mangled name。C++正是靠这种编译机制实现了重载,比如另有一个重载函数void foo( int x, floaty );则编译后符号库中的名字为_foo_int_float。
这样就容易理解了,一个用C编写和编译的函数,如果需要在一个C++程序中调用和使用它,必须用extern "C",因为extern "C"能够保证对调用的C函数采用C的方式对其进行编译;否则,由于编译后符号库的名字不匹配,连接器在C的obj中找不到匹配的函数,则出现连接错误。
2,值得注意的是:不仅仅是全局函数,使用C中定义的全局变量也要放在extern "C"的{}中。
3,extern "C"中也可以添加整个C的头文件(#include)。
4,由于C不支持extern "C",所以出现了源文件中的条件编译语句(#ifdef...#endif)。
查看obj文件中符号库的方法:
vc安装目录的bin目录下有个应用程序dumpbin.exe。用如下命令行语句:
dumpbin.exe filename.obj /symbols /out:show.txt ( /out:show.txt 是将输出结果重定向到show.txt文件)
文章出处:(http://www.diybl.com/course/3_program/c++/cppjs/20091125/183420.html)
dumpbin命令问题的解决办法
http://www.cnblogs.com/neuqustciim/archive/2009/01/13/1374989.html
我们在查看一个.exe文件需要哪些.dll和一个dll会导出那些函数的时候我们都会用到dumpbin
我运行的时候dumpbin的时候总是提示dumbin是无效的命令(在DOS下的cmd命令中),按照孙鑫的视频中的方法:
说找不到是可能是环境变量遭到破坏,运行D:/Program Files/Microsoft Visual Studio 8/VC/bin/vcvars32.bat,这个批处理程序就是为VC设置环境变量的工具。但是好像我运行之后还是没有用。我直接进到D:/Program Files/Microsoft Visual Studio 8/VC/bin看到了dumpbin.exe,但是就是在这个目录下运行dumpbin也会提示找不到mspdb80.dll,当我把mspdb80.dll加到D:/Program Files/Microsoft Visual Studio 8/VC/bin下的时候是可以解决问题,但是这样做的话下次启动VS2005运行一个工程的话会出问题,会提示你fatal error C1902: 程序数据库管理器不匹配;请检查安装,上网查了一下就是因为我从common7 下把mspdb80.dll拷贝到bin下,但是没有及时删除造成的。可以参考http://topic.csdn.net/u/20071112/12/f2e5e61c-a591-4706-81b3-972f938b00af.html
看来dumpbin.exe的运行是依赖于mspdb80.dll,但是我们把mspdb80.dll从common7下移动到vc/bin下面又会造成VS的运行错误。我们知道一个.exe找.dll的顺序是1)进程的当前目录 2)windows目录下的系统目录是c:/windows/system32/目录这个吧 3)Windows目录 4)PATH环境变量中列出的目录。看来是不能有两个mspdb80.dll那我就让dumpbin.exe运行的时候自己去找common7下的mspdb80.dll不就OK了。
步骤一:
在环境变量中的PATH变量中添加D:/Program Files/Microsoft Visual Studio 8/VC/bin;D:/Program Files/Microsoft Visual Studio 8/Common7/IDE路径
这下子在D:/Program Files/Microsoft Visual Studio 8/VC/bin下运行dumpbin.exe没有问题了,而且解决了VS2005启动时的错误问题,但是我们想在当前的工程的目录下来看.dll的属性。而不像把.dll拷到VC/bin下面去看,如何解决?还是用环境变量PATH中添加路径运行vcvars32.bat或是手动加上D:/Program Files/Microsoft Visual Studio 8/VC/bin应该都可以,后来我又没有自己手动加上这一路径
步骤二:
运行vcvars32.bat或手动加上D:/Program Files/Microsoft Visual Studio 8/VC/bin
这样运行再运行dumpbin命令就OK了
2009-03-12 08:22:08
例:
两个文件:
c文件:C.c
int external=5; //全局变量,缺省为extern。 int func() //全局函数,缺省为extern。 { return external; }
cpp文件:CPP.cpp
#include "iostream" using namespace std; //extern int external; //报错,证明C++编译时的关于变量的符号也不一样 //如果这里(cpp文件里)定义同名的int型变量external,编译器会认为是另外一个变量 //不会报错。 #ifdef __cplusplus extern "C" { #endif extern int external; //告诉编译器extern是在别的文件中定义的int,这里并不会为其分配存储空间。 extern int func(); //虽然这两个都是在extern "C"的{}里,但是仍然要显式指定extern,否则报错。 #ifdef __cplusplus //不仅仅是函数,变量也要放在extern "C"中。 } #endif void main(void) { cout<<"the value of external in c file is: "<<external<<endl; external=10; cout<<"after modified in cpp is : "<<func()<<endl; }
在讨论extern "C"之前先来讨论extern。
1、C/C++里全局变量和全局函数的定义缺省是extern的。即如果一个project由好几个文件组成,那么在A文件的全局作用域中定义了全局变量或者全局函数,默认情况下在其他文件中是可见的,即其他的文件只要在自己的全局作用域中用extern显式声明A中的全局变量和函数,就可以使用A中定义的全局变量和全局函数。
2、需要注意的一点是,extern int external 这样的声明并不为external分配内存空间。这里只是一个声明,它告诉编译器 external 这个变量是在其他文件中定义。因此,在编译的时候即使找不到external的定义也不会报错,因为连接的时候会在其他文件的obj中找到external。
3、cout<<"the value of external in c file is: "<<external<<endl;
external=10;
cout<<"after modified in cpp is : "<<func()<<endl;
用这三句代码来说明extern:变量external是在C.c文件中定义的,CPP.cpp只是声明了一下,它告诉编译器CPP中用到的external是在别的文件中定义的。
首先,打印出external的值,为5(C文件中定义externl为5,这更加说明了CPP中并不为external开辟新空间,否则应该为0),
然后,在CPP文件中将external改为10,通过调用func()显式external的值。func()是C中的函数,它返回external的值,结果打印出10(进一步说明了external定义在C,使用在CPP)。
4、声明的时候,如果去掉变量前面的extern,将会出现连接错误,提示定义了两个同名变量。
5、与extern对应的是static。在全局作用域里用static显式声明的变量和函数说明它们只能供其所在的文件使用,其他文件对其不可见;如果是在模块中声明一个static变量,则这个变量的作用域还是所在模块,但是生命周期延长到程序结束。
再来看extern "C"
extern "C" 的引用就是为了解决C++语言和C语言的混合编程问题。
C++支持的函数重载机制导致了C和C++编译机制的不同。
1,比如对一个函数
void foo( int x, int y );
由C编译器编译后符号库中的名字为_foo;而C++编译器编译后则为_foo_int_int,称为mangled name。C++正是靠这种编译机制实现了重载,比如另有一个重载函数void foo( int x, floaty );则编译后符号库中的名字为_foo_int_float。
这样就容易理解了,一个用C编写和编译的函数,如果需要在一个C++程序中调用和使用它,必须用extern "C",因为extern "C"能够保证对调用的C函数采用C的方式对其进行编译;否则,由于编译后符号库的名字不匹配,连接器在C的obj中找不到匹配的函数,则出现连接错误。
2,值得注意的是:不仅仅是全局函数,使用C中定义的全局变量也要放在extern "C"的{}中。
3,extern "C"中也可以添加整个C的头文件(#include)。
4,由于C不支持extern "C",所以出现了源文件中的条件编译语句(#ifdef...#endif)。
查看obj文件中符号库的方法:
vc安装目录的bin目录下有个应用程序dumpbin.exe。用如下命令行语句:
dumpbin.exe filename.obj /symbols /out:show.txt ( /out:show.txt 是将输出结果重定向到show.txt文件)
文章出处:(http://www.diybl.com/course/3_program/c++/cppjs/20091125/183420.html)
dumpbin命令问题的解决办法
http://www.cnblogs.com/neuqustciim/archive/2009/01/13/1374989.html
我们在查看一个.exe文件需要哪些.dll和一个dll会导出那些函数的时候我们都会用到dumpbin
我运行的时候dumpbin的时候总是提示dumbin是无效的命令(在DOS下的cmd命令中),按照孙鑫的视频中的方法:
说找不到是可能是环境变量遭到破坏,运行D:/Program Files/Microsoft Visual Studio 8/VC/bin/vcvars32.bat,这个批处理程序就是为VC设置环境变量的工具。但是好像我运行之后还是没有用。我直接进到D:/Program Files/Microsoft Visual Studio 8/VC/bin看到了dumpbin.exe,但是就是在这个目录下运行dumpbin也会提示找不到mspdb80.dll,当我把mspdb80.dll加到D:/Program Files/Microsoft Visual Studio 8/VC/bin下的时候是可以解决问题,但是这样做的话下次启动VS2005运行一个工程的话会出问题,会提示你fatal error C1902: 程序数据库管理器不匹配;请检查安装,上网查了一下就是因为我从common7 下把mspdb80.dll拷贝到bin下,但是没有及时删除造成的。可以参考http://topic.csdn.net/u/20071112/12/f2e5e61c-a591-4706-81b3-972f938b00af.html
看来dumpbin.exe的运行是依赖于mspdb80.dll,但是我们把mspdb80.dll从common7下移动到vc/bin下面又会造成VS的运行错误。我们知道一个.exe找.dll的顺序是1)进程的当前目录 2)windows目录下的系统目录是c:/windows/system32/目录这个吧 3)Windows目录 4)PATH环境变量中列出的目录。看来是不能有两个mspdb80.dll那我就让dumpbin.exe运行的时候自己去找common7下的mspdb80.dll不就OK了。
步骤一:
在环境变量中的PATH变量中添加D:/Program Files/Microsoft Visual Studio 8/VC/bin;D:/Program Files/Microsoft Visual Studio 8/Common7/IDE路径
这下子在D:/Program Files/Microsoft Visual Studio 8/VC/bin下运行dumpbin.exe没有问题了,而且解决了VS2005启动时的错误问题,但是我们想在当前的工程的目录下来看.dll的属性。而不像把.dll拷到VC/bin下面去看,如何解决?还是用环境变量PATH中添加路径运行vcvars32.bat或是手动加上D:/Program Files/Microsoft Visual Studio 8/VC/bin应该都可以,后来我又没有自己手动加上这一路径
步骤二:
运行vcvars32.bat或手动加上D:/Program Files/Microsoft Visual Studio 8/VC/bin
这样运行再运行dumpbin命令就OK了
相关文章推荐
- 关于"error LNK2019: unresolved external symbol _SipShowIM referenced in function "protected" 解决方法
- 一篇不错的关于js"闭包"的文章
- 关于error LNK2001: unresolved external symbol "__declspec(dllimport) public
- 关于翻译"asp.net2.0数据操作指南"系列文章的说明
- 关于extern "C"的一篇很好的文章
- 关于"testencodefile.obj : error LNK2001: unresolved external symbol "__declspec(dllimport) public"
- NHibernate3.3.0GA+ExtJS4.1.1+ASP.NET MVC3.0权限管理系统(4)--关于(3)报错"Cannot read property 'addCls' of null"
- 关于C#中的错误:The type 'X' does not exists in the "Y"
- Struts2中关于"There is no Action mapped for namespace / and action name"的总结
- Sharepoint 2013 关于"SPChange"简介
- 关于"猪肉涨价,内存降价。"的评论!
- 关于 "Adodb.Stream" 组件的属性,方法手册
- FCKeditor关于图片上传出现错误“ 提示没有权限 Type=Image” 以及出现"this connector is disabled Please check the"editor/filemanager/connectors/aspx/conf
- 关于VC"致命错误 RC1004: 文件查找结束时有无法预知的错误"
- 昨晚两篇"待审核"的文章不翼而飞了
- 关于解决"cannot modify header information - headers already sent by"的错误
- 关于protues 中提示“can not open "C.................LISA3199.SDF”的问题的解决
- 关于反射Assembly.Load("程序集").CreateInstance("命名空间.类")
- 关于"黑苹果" 的安装方法
- [c、c++]宏中"#"和"##"的用法(zz)