如何在C++中调用C的代码

以前曾经总结过一篇(http://www.cppblog.com/franksunny/archive/2007/11/29/37510.html ),关于在 C 中如何调用 C++ 的代码,当时并未做完全的展开,只是简单的做了下调试,最近看到一个题目要求实现 C C++ 中代码的互相调用,其结果虽然都是通过 extern “C” 来实现 ,但是具体还是有些差别的。

先对 C 中调用 C++ 代码作个简单回顾:

1、              对于 C++ 中非类的成员函数,可以简单的在函数声明前面加 extern “C” ,通常函数声明位于头文件中,当然也可以将声明和函数定义一起放在 cpp ,在没有声明的情况下,直接在定义前添加 extern “C” 也可

2、              对于 C++ 类的成员函数,则需要另外做一个 cpp 文件,将需要调用的函数进行包装

以上两项的实例参看前面 C 中如何调用 C++ 代码的文章。

要实现 C++ 中调用 C 的代码,具体操作:

对于 C 中的函数代码,要么 C 代码的头文件进行修改,在其被含入 C++ 代码时在声明中加入 extern “C” 或者 C++ 代码中重新声明一下 C 函数,重新声明时添加上 extern “C”

通过以上的说明,我明白一点,那就是 extern “C” 头一定是加在 C++ 的代码文件中才能起作用的

 

下面分析一下这个现象的实质原因:

C 编译器编译函数时不带函数的类型信息,只包含函数符号名字,如 C 编译器把函数 int a(float x) 编译成类似 _a 这样的符号, C 连接器只要找到了调用函数的符号,就可以连接成功,它假设参数类型信息是正确的,这是 C 编译连接器的缺点。而 C++ 编译器为了实现函数重载,编译时会带上函数的类型信息,如他把上面的 a 函数可能编译成 _a_float 这样的符号为了实现重载,注意它还是没有带返回值得信息,这也是为什么 C++ 不支持采用函数返回值来区别函数重载的原因之一,当然,函数的使用者对函数返回值的处理方式(如忽略)也是重要原因。

基于以上, C 调用 C++ ,首先需要用封装函数把对 C++ 的类等的调用封装成 C 函数以便 C 调用,于是 extern "C" 的作用是:让编译器知道这件事,然后 C 语言的方式编译和连接封装函数 通常是把封装函数用 C++ 编译器按 C++ 方式编译,用了 extern "C" 后,编译器便依 C 的方式编译封装接口,当然接口函数里面的 C++ 语法还是按 C++ 方式编译;对于 C 语言部分 -- 调用者,还是按 C 语言编译;分别对 C++ 接口部分和 C 部分编译后,再连接就可以实现 C 调用 C++ )。相反 ,C++ 调用 C 函数, extern "C" 的作用是:让 C++ 连接器找调用函数的符号时采用 C 的方式 ,即使用 _a 而不是 _a_float 来找调用函数。

 

具体示例请见 http://www.cppblog.com/Files/franksunny/CCallCpp.rar

注:如果你用 VC6.0 编译附件时遇到类似 “fatal error C1010: unexpected end of file while looking for precompiled header directive” 报错的话,请将 bb.c 文件做如下处理右键点击项目工程中的该文件,选择 setting ,在 c/c++ 栏,选择 PreCompiled headers ,然后设置第一选项,选择不使用预编译头。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值