C和C++混合編程問題
分析以下一段代碼:
/*=======sum.h=========*/
#ifndef SUM_H
#define SUM_H
#include <stdio.h>
int sum(int a,int b);
#endif;
/*=======sum.c=========*/
#include "sum.h"
int sum(int a,int b)
{
int c=a+b;
return c;
}
/*====main.cpp======*/
#include "sum.h"
void mian(){
cout << sum(1,2)<<endl;
}
調(diào)用以上三個(gè)文件,編譯通過,但是執(zhí)行是出現(xiàn)以下問題:
obj : error LNK2001: 無法解析的外部符號(hào) "int __cdecl sum(int,int)" (?sum@@YAHHH@Z)
E:\Programming\Grapic\test\Debug\test.exe : fatal error LNK1120: 1 個(gè)無法解析的外部命令
問題出在哪里呢? 在main.cpp里調(diào)用了sum.c,也就是說在C++程序里調(diào)用了C程序,此時(shí)如果沒有作相應(yīng)處理將會(huì)出現(xiàn)鏈接錯(cuò)誤。
extern "C"表示編譯生成的內(nèi)部符號(hào)名使用C約定。C++支持函數(shù)重載,而C不支持,兩者的編譯規(guī)則也不一樣。函數(shù)被C++編譯后在符號(hào)庫(kù)中的名字與C語(yǔ)言的不同。例如,假設(shè)某個(gè)函數(shù)的原型為:void foo( int x, int y ); 該函數(shù)被C編譯器編譯后在符號(hào)庫(kù)中的名字可能為_foo,而C++編譯器則會(huì)產(chǎn)生像_foo_int_int之類的名字(不同的編譯器可能生成的名字不同,但是都采用了相同的機(jī)制,生成的新名字稱為“mangled name”)。_foo_int_int這樣的名字包含了函數(shù)名、函數(shù)參數(shù)數(shù)量及類型信息,C++就是靠這種機(jī)制來實(shí)現(xiàn)函數(shù)重載的。
那么如果在C中調(diào)用C++代碼,以及如何在C++中調(diào)用C的代碼呢?
extern "C"表示編譯生成的內(nèi)部符號(hào)名使用C約定。
1. 如何在C++中調(diào)用C呢?
C++調(diào)用C,extern "C" 的作用是:讓C++連接器找調(diào)用函數(shù)的符號(hào)時(shí)采用C的方式
本文開頭提出的筆試題可以這樣修改:
/*=======sum.h=========*/
#ifndef SUM_H
#define SUM_H
#include <stdio.h>
int sum(int a,int b);
#endif;
/*=======sum.c=========*/
#include "sum.h"
int sum(int a,int b)
{
int c=a+b;
return c;
}
/*====main.cpp======*/
extern "C"
{
#include "sum.h"
}
void mian(){
cout << sum(1,2)<<endl;
}
執(zhí)行成功
相信到這里差不多明白了
2. 怎樣在C里調(diào)用C++呢?
在C中引用C++函數(shù)(C調(diào)用C++,使用extern "C"則是告訴編譯器把cpp文件中extern "C"定義的函數(shù)依照C的方式來編譯封裝接口,當(dāng)然接口函數(shù)里面的C++語(yǔ)法還是按C++方式編譯)
執(zhí)行:test1.obj : error LNK2019: 無法解析的外部符號(hào) _sum,該符號(hào)在函數(shù) _main 中被引用
E:\Programming\Grapic\test\Debug\test.exe : fatal error LNK1120: 1 個(gè)無法解析的外部命令
/*=======sum.h=========*/
#ifndef SUM_H
#define SUM_H
#include <stdio.h>
int sum(int a,int b);
#endif;
/*=======sum.cpp=========*/
#include "sum.h"
extern "C"
{
int sum(int a,int b)
{
int c=a+b;
return c;
}
}
/*====main.c======*/
#include "sum.h"
void mian(){
cout << sum(1,2)<<endl;
}
3. 標(biāo)準(zhǔn)規(guī)范寫法
一般我們都將函數(shù)聲明放在頭文件,當(dāng)我們的函數(shù)有可能被C或C++使用時(shí),我們無法確定被誰(shuí)調(diào)用,使得不能確定是否要將函數(shù)聲明在extern "C"里,所以,我們可以添加
#ifdef __cplusplus
extern "C"
{
#endif
//函數(shù)聲明
#ifdef __cplusplus
}
#endif
利用以上聲明形式就可以綜合運(yùn)用了。
在C中引用C++語(yǔ)言中的函數(shù)和變量時(shí),C++的函數(shù)或變量要聲明在extern "C"{}里,但是在C語(yǔ)言中不能使用extern "C",否則編譯出錯(cuò)。(出現(xiàn)錯(cuò)誤: error C2059: syntax error : 'string',這個(gè)錯(cuò)誤在網(wǎng)上找了很久,國(guó)內(nèi)網(wǎng)站沒有搜到直接說明原因的,原因是extern "C"是C++中的關(guān)鍵詞,不是C的,所有會(huì)出錯(cuò)。
/*=======sum.h=========*/
#ifndef SUM_H
#define SUM_H
#include <stdio.h>
int sum(int a,int b);
#endif;
/*=======sum.cpp=========*/
#include "sum.h"
int sum(int a,int b)
{
int c=a+b;
return c;
}
/*====main.c======*/
#include "sum.h"
void mian(){
cout << sum(1,2)<<endl;
}
相關(guān)文章
C語(yǔ)言中回調(diào)函數(shù)和qsort函數(shù)的用法詳解
這篇文章主要為大家詳細(xì)介紹一下C語(yǔ)言中回調(diào)函數(shù)和qsort函數(shù)的用法教程,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)C語(yǔ)言有一定幫助,需要的可以參考一下2022-07-07
C++中double浮點(diǎn)數(shù)精度丟失的深入分析
這篇文章主要給大家介紹了關(guān)于C++中double浮點(diǎn)數(shù)精度丟失的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
使用Qt實(shí)現(xiàn)獲取本機(jī)IP和定位
這篇文章主要為大家詳細(xì)介紹了如何使用Qt實(shí)現(xiàn)獲取本機(jī)IP和定位,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-11-11
c語(yǔ)言執(zhí)行Hello?World背后經(jīng)歷的步驟
這篇文章介紹了c語(yǔ)言執(zhí)行Hello?World背后經(jīng)歷的步驟,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12

