您的位置:首页 > 其它

zz 关于external "C"的文章

2010-03-31 14:03 323 查看
EXTERNAL C的用法
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了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐