手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>程序设计>C/C++>列表

c, c 库调用相关知识

来源:互联网 作者:west263.com 时间:2008-02-23
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!
1。 重载是如何实现的?

几个同名的重载函数仍然是不同的函数,他们是如何区分的呢?我们自然想到函数接口的两个要素:参数和返回值。

假如同名函数的参数不同(包括类型、顺序不同),那么容易区别出他们是不同的函数。

假如同名函数仅仅是返回值类型不同,有时能够区分,有时却不能。例如:

void Function(void);

int Function (void);

上述两个函数,第一个没有返回值,第二个的返回值是int类型。假如这样调用函数:

int x = Function ();

则能够判断出Function是第二个函数。问题是在C /C程式中,我们能够忽略函数的返回值。在这种情况下,编译器和程式员都不知道哪个Function函数被调用。

所以只能靠参数而不能靠返回值类型的不同来区分重载函数。编译器根据参数为每个重载函数产生不同的内部标识符。例如编译器为示例8-1-1中的三个Eat 函数产生象_eat_beef、_eat_fish、_eat_chicken之类的内部标识符(不同的编译器可能产生不同风格的内部标识符)。



假如C 程式要调用已被编译后的C函数,该怎么办?

假设某个C函数的声明如下:

void foo(int x, int y);

该函数被C编译器编译后在库中的名字为_foo,而C 编译器则会产生像_foo_int_int之类的名字用来支持函数重载和类型安全连接。 由于编译后的名字不同,C 程式不能直接调用C函数。C 提供了一个C连接交换指定符号extern“C”来解决这个问题。例如:

extern “C”

{

void foo(int x, int y);

… // 其他函数

}

或写成

extern “C”

{

#include “myheader.h”

… // 其他C头文档

}

这就告诉C 编译译器,函数foo是个C连接,应该到库中找名字_foo而不是找_foo_int_int。C 编译器研发商已对C标准库的头文档作了extern“C”处理,所以我们能够用#include 直接引用这些头文档。



注意并不是两个函数的名字相同就能构成重载。全局函数和类的成员函数同名不算重载,因为函数的作用域不同。例如:

void Print(…); // 全局函数

class A

{…

void Print(…); // 成员函数

}

不论两个Print函数的参数是否不同,假如类的某个成员函数要调用全局函数Print,为了和成员函数Print区别,全局函数被调用时应加‘::’标志。如

::Print(…); // 表示Print是全局函数而非成员函数
一句话,extern "C" 用到的地方:
1). c 库相关的头文档中,如 c.h 中(使 C 能调用 c库中函
数):
#ifdef __cplusplus
extern "C"{
#endif
...函数声明...
#ifdef __cplusplus
}
#endif
2). 有时候在 C 中,要调用 c 库中的函数 funcA()
extern "C"
{
funcA();
}

extern "C"
{
#include "c.h"
}

2. c库和 C 库的调用关系。
简单的说就是 C 能够调用 c 的, c 不能调用 C 的。
如:
1)g -o exe main.cpp myc.o/myc.a/myc.so
能够。 //main.cpp 要调用 myc 中的函数。注意 extern "C"
2)gcc -o exe main.c myc .o/myc .a/myc .so
不行。 //main.c 要调用 myc 中的函数。
3)A: mylibc.o/mylibc.a/mylibc.so 中一函数为
FunC()
{
FunCplus();
}
B: mylibc .o/mylibc .a/mylibc .so 中一函数为
FunCplus();
此时, main.cpp 调用 FunC ();
g -o exe main.cpp A B 也编译但是,道理和 2)差不多。
4)A: mylibc.o/mylibc.a/mylibc.so 中一函数为
int funC(int);
B: mylibc .o/mylibc .a/mylibc .so 中一函数为
int funCplus(int)
此时, main.cpp 中有:
funC(funCplus(para));
funCplus(funC(para));
g -o exe main.cpp A B 能够编译成功并运行。

3.编译到目标的内容
(静态库)在编译可执行程式时,只有程式中确实用到的函数才会被包括进去,虽然一个头文档里包含着函数库中的全体函数声明,但在可执行程式中使用 include 语句引用,他并不会把整个函数库的内容都包括到可执行文档中去。

4.从 so 库封装 so 库。
已有 libqt-mt.so.3.3.4(base.so),若 g midlib.cpp 中调用了
libqt-mt.so.3.3.4(base.so) 中的函数,且又要被编译为一个共享库(so), main.cpp 调用该生成的新共享库。

1)g -shared -o libg midlib.so g midlib.cpp -I/root/QT/qt-x11-free-3.3.4/include /root/QT/qt-x11-free-3.3.4/lib/libqt-mt.so.3.3.4
g -o exe libg midlib.so main.cpp -I/root/QT/qt-x11-free-3.3.4/inlucde

2) g -shared -o libg midlib.so g midlib.cpp -I/root/QT/qt-x11-free-3.3.4/include
g -o exe libg midlib.so main.cpp -I/root/QT/qt-x11-free-3.3.4/include /root/QT/qt-x11-free-3.3.4/lib/libqt-mt.so.3.3.4

在这两种情况下生成的可执行文档 exe,都仅只需要有新生成的库 libg midlib.so 就能够运行了。

2---4 运行的环境(估计其他的也差不多):
Linux localhost.localdomain 2.4.20-8 #1 Thu Mar 13 17:54:28 EST 2003 i686 i686 i386 GNU/Linux

[root@localhost bin]# gcc -v
Reading specs from /usr/lib/gcc-lib/i386-redhat-linux/3.2.2/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
Thread model: posix
gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)



文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

热点关注
IDC资讯 虚拟主机 域名注册 托管租用 vps主机 智能建站
网站运营 建站经验 策划盈利 搜索优化 网站推广 免费资源
网站联盟 联盟新闻 联盟介绍 联盟点评 网赚技巧
行业资讯 业界动态 搜索引擎 网络游戏 门户动态 电子商务 广告传媒
网络编程 Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术 Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷 Internet Explorer
网页制作 FrontPages Dreamweaver Javascript css photoshop fireworks Flash
程序设计 Java技术 C/C++ VB delphi
网络知识 网络协议 网络安全 网络管理 组网方案 Cisco技术
操作系统 Win2000 WinXP Win2003 Mac OS Linux FreeBSD
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 价格总览 | 资讯中心 | 友情链接 | 网站地图 | 招贤纳士 | RSS