日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

【C++ 语言】 C 与 C++ 兼容 ( extern C )

發布時間:2025/6/17 c/c++ 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【C++ 语言】 C 与 C++ 兼容 ( extern C ) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

        • 創建項目
        • 項目源碼說明
        • C++ 中直接調用 C 代碼 ( 無法解析的外部符號 錯誤 )
        • C++ 與 C 編譯結果對比
        • extern "C" 在頭文件中的標準用法
        • 最終的 C / C ++ 兼容 代碼



創建項目


創建 并運行 CMake 項目 :

  • 1. 選擇創建選項 : 在打開的歡迎界面中 , 點擊 右側最下方的 "創建新項目 " 選項 ;

  • 2. 選擇項目類型 : 選擇創建 “CMake 項目” , 在 Android 中主要使用的也是 CMake 配置 NDK C/C++ 代碼 ;

  • 3. 項目配置 : 輸入項目名稱 , 選擇項目位置 , 下面的解決方案名稱會自動生成 , 不勾選最下方的選項 ; 點擊 “創建” 按鈕 , 創建項目 ;


等待項目創建完畢 , 會自動跳轉到程序主界面 ;

  • 4. 自動生成解決方案 : 進入程序主界面后 , 系統會自動生成 CMake 解決方案 , 如果一切順利 , 會有如下結果 :

5. 選擇啟動項 : 點擊綠色的小三角按鈕 “選擇啟動項” , 選擇上面生成的解決方案 “001_CMake_1.exe” 選項 , 如下圖示 ;

  • 6. 運行程序 : 再次點擊 “001_CMake_1.exe” 選項 , 即可運行該控制臺程序 , 在控制臺中打印 “Hello CMake。” ;



項目源碼說明


相關源碼說明 :


① 001_CMake_1.h : 項目頭文件 ;

// 001_CMake_1.h: 標準系統包含文件的包含文件 // 或項目特定的包含文件。#pragma once#include <iostream>// TODO: 在此處引用程序需要的其他標頭。

② 001_CMake_1.cpp : 項目主代碼文件 ;

// 001_CMake_1.cpp: 定義應用程序的入口點。 //#include "001_CMake_1.h"using namespace std;int main() {cout << "Hello CMake。" << endl;return 0; }

C 與 C++ 標準輸出 :

  • C 中的標準輸出 : 直接調用 printf
printf("Hello");
  • C++ 中的標準輸出 : << 此處是 操作符重載 , cout 在 std 命名空間中 ;
cout << "Hello" << endl;

③ CMakeLists.txt ( 工程目錄下 ) : 項目構建配置文件 , 配置 構建工具版本號 , 項目編譯所需的源代碼 ;

# CMakeList.txt: 001_CMake_1 的 CMake 項目,在此處包括源代碼并定義 # 項目特定的邏輯。 # cmake_minimum_required (VERSION 3.8)# 將源代碼添加到此項目的可執行文件。 add_executable (001_CMake_1 "001_CMake_1.cpp" "001_CMake_1.h")# TODO: 如有需要,請添加測試并安裝目標。

④ CMakeLists.txt ( 總目錄下 ) : 頂層的 CMake 文件, 配置全局所有子項目信息 , 這里只有一個子項目 ;

# CMakeList.txt: 頂層 CMake 項目文件,在此處執行全局配置 # 并包含子項目。 # cmake_minimum_required (VERSION 3.8)project ("001_CMake_1")# 包含子項目。 add_subdirectory ("001_CMake_1")


C++ 中直接調用 C 代碼 ( 無法解析的外部符號 錯誤 )


C++ 向下兼容 : C 中大部分代碼都可以在 C++ 中直接使用 ; 但是需要做兼容處理 , 不能直接使用 ;


1. 創建測試文件 : 在上述創建的項目中 , 創建 c_extern.c 和 c_extern.h 兩個文件 ;


2. c_extern.h 頭文件內容 : 在頭文件中定義一個帶參數的方法 ;

#pragma once//任意定義一個方法 , 該方法有若干個參數和返回值 int add(int a, int b);

3. c_extern.c 源文件內容 : 在 C 語言文件中實現上述頭文件中定義的帶參數的方法 ;

#include "c_extern.h"//實現的頭文件中的方法, 用于測試 C 與 C++ 兼容問題 int add(int a, int b) {return 0; }

4. CMake 配置源碼 : 將 “c_extern.c” ( C文件 ) 和 “c_extern.h” ( 頭文件 ) 配置到 CMakeLists.txt 中 ;

# CMakeList.txt: 001_CMake_1 的 CMake 項目,在此處包括源代碼并定義 # 項目特定的邏輯。 # cmake_minimum_required (VERSION 3.8)# 將源代碼添加到此項目的可執行文件。 add_executable (001_CMake_1 "001_CMake_1.cpp" "001_CMake_1.h" "c_extern.c" "c_extern.h")# TODO: 如有需要,請添加測試并安裝目標。

5. 執行結果 : 點擊 001_CMake_1.exe 選項 , 運行程序 ; 彈出 “生成失敗 , 是否要繼續調試?” 的對話框 , 此時


6. 錯誤提示 : 無法解析在 main 函數中調用的 add 方法 ;

嚴重性 代碼 說明 項目 文件 行 禁止顯示狀態 錯誤 LNK1120 1 個無法解析的外部命令 ...\CMakeLists.txt ...\001_CMake_1.exe 1 錯誤 LNK2019 無法解析的外部符號 "int __cdecl add(int,int)" (?add@@YAHHH@Z), 該符號在函數 main 中被引用 ...\CMakeLists.txt ...\001_CMake_1.cpp.obj 1

在 C++ 源碼中直接調用 C 源碼 , 一定會報該錯誤 , 下面分析產生該錯誤的原因 , 以及如何進行兼容處理 ;




C++ 與 C 編譯結果對比


1. 創建對比文件 : 創建 下面 兩個文件 , 分別是 C 代碼 和 C++ 代碼 ;

① c_code.c :

int add (int a, int b){return a+b; }int main(){return 0; }

② c_plus_code.cpp :

int add (int a, int b){return a+b; }int main(){return 0; }

C 和 C++ 中代碼內容一模一樣 ;


2. 獲取 c_code.c 編譯過程中的 機器碼文件 : 使用 gcc c_code.c -o c_code.o 命令 , 可以獲取編譯的中間文件 , 輸出到 c_code.o 文件中 ;


3. 獲取 C語言文件編譯后的 機器碼文件中對應的符號 : 使用 nm -A c_code.o 命令 , 可以查看 c_code.o 二進制文件中的符號 ;

輸出詳細內容 :

root@ubuntu:~/001_c_c++# gcc c_code.c -o c_code.o root@ubuntu:~/001_c_c++# root@ubuntu:~/001_c_c++# ls c_code.c c_code.o c_plus_code.cpp root@ubuntu:~/001_c_c++# root@ubuntu:~/001_c_c++# nm -A c_code.o c_code.o:00000000004004d6 T add c_code.o:0000000000601030 B __bss_start c_code.o:0000000000601030 b completed.7594 c_code.o:0000000000601020 D __data_start c_code.o:0000000000601020 W data_start c_code.o:0000000000400410 t deregister_tm_clones c_code.o:0000000000400490 t __do_global_dtors_aux c_code.o:0000000000600e18 t __do_global_dtors_aux_fini_array_entry c_code.o:0000000000601028 D __dso_handle c_code.o:0000000000600e28 d _DYNAMIC c_code.o:0000000000601030 D _edata c_code.o:0000000000601038 B _end c_code.o:0000000000400574 T _fini c_code.o:00000000004004b0 t frame_dummy c_code.o:0000000000600e10 t __frame_dummy_init_array_entry c_code.o:00000000004006d0 r __FRAME_END__ c_code.o:0000000000601000 d _GLOBAL_OFFSET_TABLE_ c_code.o: w __gmon_start__ c_code.o:0000000000400584 r __GNU_EH_FRAME_HDR c_code.o:0000000000400390 T _init c_code.o:0000000000600e18 t __init_array_end c_code.o:0000000000600e10 t __init_array_start c_code.o:0000000000400580 R _IO_stdin_used c_code.o: w _ITM_deregisterTMCloneTable c_code.o: w _ITM_registerTMCloneTable c_code.o:0000000000600e20 d __JCR_END__ c_code.o:0000000000600e20 d __JCR_LIST__ c_code.o: w _Jv_RegisterClasses c_code.o:0000000000400570 T __libc_csu_fini c_code.o:0000000000400500 T __libc_csu_init c_code.o: U __libc_start_main@@GLIBC_2.2.5 c_code.o:00000000004004ea T main c_code.o:0000000000400450 t register_tm_clones c_code.o:00000000004003e0 T _start c_code.o:0000000000601030 D __TMC_END__ root@ubuntu:~/001_c_c++#

4. 分析上述輸出內容 : 由 第一行 c_code.o:00000000004004d6 T add 可以看出 , add 方法編譯后的符號為 add ;


5. 獲取 c_plus_code.cpp 編譯過程中的 機器碼文件 : 使用 gcc c_plus_code.cpp -o c_plus_code.o 命令 , 可以獲取編譯的中間文件 , 輸出到 c_plus_code.o 文件中 ;

root@ubuntu:~/001_c_c++# gcc c_plus_code.cpp -o c_plus_code.o root@ubuntu:~/001_c_c++# ls c_code.c c_code.o c_plus_code.cpp c_plus_code.o root@ubuntu:~/001_c_c++# root@ubuntu:~/001_c_c++# nm -A c_plus_code.o c_plus_code.o:0000000000601030 B __bss_start c_plus_code.o:0000000000601030 b completed.7594 c_plus_code.o:0000000000601020 D __data_start c_plus_code.o:0000000000601020 W data_start c_plus_code.o:0000000000400410 t deregister_tm_clones c_plus_code.o:0000000000400490 t __do_global_dtors_aux c_plus_code.o:0000000000600e18 t __do_global_dtors_aux_fini_array_entry c_plus_code.o:0000000000601028 D __dso_handle c_plus_code.o:0000000000600e28 d _DYNAMIC c_plus_code.o:0000000000601030 D _edata c_plus_code.o:0000000000601038 B _end c_plus_code.o:0000000000400574 T _fini c_plus_code.o:00000000004004b0 t frame_dummy c_plus_code.o:0000000000600e10 t __frame_dummy_init_array_entry c_plus_code.o:00000000004006d0 r __FRAME_END__ c_plus_code.o:0000000000601000 d _GLOBAL_OFFSET_TABLE_ c_plus_code.o: w __gmon_start__ c_plus_code.o:0000000000400584 r __GNU_EH_FRAME_HDR c_plus_code.o:0000000000400390 T _init c_plus_code.o:0000000000600e18 t __init_array_end c_plus_code.o:0000000000600e10 t __init_array_start c_plus_code.o:0000000000400580 R _IO_stdin_used c_plus_code.o: w _ITM_deregisterTMCloneTable c_plus_code.o: w _ITM_registerTMCloneTable c_plus_code.o:0000000000600e20 d __JCR_END__ c_plus_code.o:0000000000600e20 d __JCR_LIST__ c_plus_code.o: w _Jv_RegisterClasses c_plus_code.o:0000000000400570 T __libc_csu_fini c_plus_code.o:0000000000400500 T __libc_csu_init c_plus_code.o: U __libc_start_main@@GLIBC_2.2.5 c_plus_code.o:00000000004004ea T main c_plus_code.o:0000000000400450 t register_tm_clones c_plus_code.o:00000000004003e0 T _start c_plus_code.o:0000000000601030 D __TMC_END__ c_plus_code.o:00000000004004d6 T _Z3addii root@ubuntu:~/001_c_c++#

6. 分析上述輸出內容 : 由 最后一行 c_plus_code.o:00000000004004d6 T _Z3addii 可以看出 , add 方法編譯后的符號為 _Z3addii ;


處理完畢后的文件內容 :

7. 總結 :

  • ① 編譯結果對比 : C 語言 add 方法編譯后的符號是 add , C++ 編譯后的符號是 _Z3addii , 顯然二者不能互相調用 , 因此一旦在 C++ 中調用 add , 就會出現上述無法解析外部符號錯誤 ;
  • ② 兼容 : 如果在 C++ 文件中調用 C 語言庫 , 需要做兼容處理 ;
  • ③ 示例 : 在 Android 中的 NDK 接口是 C++ 語言的 , 但是調用的庫 如 OpenSL ES , FFMPEG 等都是 C語言的庫 , 因此這里就需要用到 C 與 C++ 的兼容 ;
  • ④ 兼容方法 : 使用 extern “C”{} 指定讓大括號中的內容 以 C 語言的方式進行編譯 ; 這樣才能在 C++ 中找到對應的 C 語言中的函數 ; 如下示例 :
extern "C"{#include "c_extern.c" }

編譯過程 : 預處理 -> 編譯 -> 匯編 -> 鏈接;
1. 編譯預處理 : 產生 .i 后綴的預處理文件;
2. 編譯操作 : 產生 .s 后綴的匯編文件;
3. 匯編操作 : 產生 .o 后綴的機器碼二進制文件;
4. 鏈接操作 : 產生可執行文件 ;




extern “C” 在頭文件中的標準用法


extern “C” 用法 :

  • 1. 在引用處使用 : extern “C” {} 可以寫在 引用 頭文件的位置 , 如下 :
// 001_CMake_1.cpp: 定義應用程序的入口點。 //#include "001_CMake_1.h"extern "C" {#include "c_extern.h" }using namespace std;int main() {cout << "Hello CMake。" << endl;//調用 c_extern.h 頭文件中定義的方法//該方法定義在了 C 語言文件中add(1, 2);return 0; }
  • 2. 在頭文件中定義 : extern “C” {} 也可以寫在 頭文件 中 , 一般情況下我們編寫的 C 代碼需要同時兼容 C 和 C++ , 因此 C 語言的頭文件都進行如下定義 :
    • ① __cplusplus 宏 : 該宏定義在 C++ 編譯器中 , 如果是 C 語言編譯器 , 就不會定義該宏 ;
    • ② 使用效果 : 如果在 C++ 編譯環境中 , extern “C” { 和 } 生效 , 在 C 語言編譯環境中 , 不生效 ;
#pragma once//兼容 C 與 C ++ 語言 , 在 C++ 中也可以編譯 C 語言程序 // __cplusplus 是編譯器中定義的 宏 //如果編譯的是 C++ 代碼 , 定義了__cplusplus 宏 , #ifdef __cplusplus 宏會生效//這一組判定 extern "C" { 聲明 , 是否生效 , 如果在 C++ 環境中生效 , C 語言環境中不生效 #ifdef __cplusplus extern "C" { #endif//任意定義一個方法 , 該方法有若干個參數和返回值int add(int a, int b);//這一組判定 } 聲明 , 是否生效 , 如果在 C++ 環境中生效 , C 語言環境中不生效 #ifdef __cplusplus } #endif

注意上述兼容二選一 , 不能同時使用 , 否則會報錯 ;




最終的 C / C ++ 兼容 代碼


最終的 C / C ++ 兼容 代碼 :

  • 1.程序結構 :
  • 2.頂層 CMakeLists.txt : 配置多個項目 ;
# CMakeList.txt: 頂層 CMake 項目文件,在此處執行全局配置 # 并包含子項目。 # cmake_minimum_required (VERSION 3.8)project ("001_CMake_1")# 包含子項目。 add_subdirectory ("001_CMake_1")
  • 3.項目 CMakeLists.txt : 配置單個項目中的多個源文件 ;
# CMakeList.txt: 001_CMake_1 的 CMake 項目,在此處包括源代碼并定義 # 項目特定的邏輯。 # cmake_minimum_required (VERSION 3.8)# 將源代碼添加到此項目的可執行文件。 add_executable (001_CMake_1 "001_CMake_1.cpp" "001_CMake_1.h" "c_extern.c" "c_extern.h")# TODO: 如有需要,請添加測試并安裝目標。
  • 4.c_extern.h :
#pragma once//兼容 C 與 C ++ 語言 , 在 C++ 中也可以編譯 C 語言程序 // __cplusplus 是編譯器中定義的 宏 //如果編譯的是 C++ 代碼 , 定義了__cplusplus 宏 , #ifdef __cplusplus 宏會生效//這一組判定 extern "C" { 聲明 , 是否生效 , 如果在 C++ 環境中生效 , C 語言環境中不生效 #ifdef __cplusplus extern "C" { #endif//任意定義一個方法 , 該方法有若干個參數和返回值int add(int a, int b);//這一組判定 } 聲明 , 是否生效 , 如果在 C++ 環境中生效 , C 語言環境中不生效 #ifdef __cplusplus } #endif
  • 5.c_extern.c :
#include "c_extern.h"//實現的頭文件中的方法, 用于測試 C 與 C++ 兼容問題 int add(int a, int b) {return 0; }
  • 7.001_CMake_1.h :
// 001_CMake_1.h: 標準系統包含文件的包含文件 // 或項目特定的包含文件。#pragma once#include <iostream>// TODO: 在此處引用程序需要的其他標頭。
  • 8.001_CMake_1.cpp :
// 001_CMake_1.cpp: 定義應用程序的入口點。 //#include "001_CMake_1.h" #include "c_extern.h"using namespace std;int main() {cout << "Hello CMake。" << endl;//調用 c_extern.h 頭文件中定義的方法//該方法定義在了 C 語言文件中add(1, 2);return 0; }
  • 9.運行結果 :

總結

以上是生活随笔為你收集整理的【C++ 语言】 C 与 C++ 兼容 ( extern C )的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲精品美女久久久 | 懂色av一区二区在线播放 | 色狠狠一区二区三区香蕉 | 精品人妻午夜一区二区三区四区 | 亚洲国产剧情 | 视频在线不卡 | 香蕉成视频人app下载安装 | 一本高清视频 | 色妞综合网 | 校园春色欧美 | 亚洲国产欧美自拍 | 成人免费视频毛片 | 8050午夜一级毛片久久亚洲欧 | 浪浪视频污| 欧美一级无毛 | 午夜视频入口 | 精品一区二区三区成人免费视频 | 草草地址线路①屁屁影院成人 | 2018天天干天天操 | 成年人看的毛片 | 久久香蕉网 | 亚洲午夜小视频 | 在线一区二区不卡 | 亚洲成人乱码 | 玖玖爱资源站 | www.69av.com| 亚洲欧洲色图 | 日日艹夜夜艹 | 国产精品精东影业 | 中文字幕乱码无码人妻系列蜜桃 | 欧美视频 | 色婷婷综合久久久中文字幕 | 干骚视频 | 精品国产乱 | 国产a级黄色 | 亚洲精品一二三四 | 99视频观看 | 蜜臀视频在线播放 | 51精品| 老司机精品在线 | 欧美亚洲另类在线 | 欧美日韩中文在线 | 中文字字幕第183页 欧美特级一级片 | 成人乱码一区二区三区 | 精品无码一区二区三区在线 | 亚洲国产成人精品久久 | 青草成人免费视频 | 欧美韩国日本在线 | 国产九九九精品 | 亚洲性生活片 | 成人网入口 | 日韩精品免费观看 | 法国空姐电影在线 | 无码人妻精品一区二区三区在线 | 91网在线看| 操的网站| 日韩电影在线一区 | 婷婷精品视频 | 亚洲天堂v | 中文字幕激情视频 | 久艹在线视频 | 欧美大片xxxx| 国产自偷自拍 | 337p粉嫩日本欧洲亚洲大胆 | 少妇被按摩师摸高潮了 | 精品xxxxx | 国产一区二区精华 | 澳门黄色 | 嫩草伊人久久精品少妇av | 久久艳片www.17c.com | 中文字幕有码在线观看 | 免费在线播放毛片 | 欧美三级韩国三级日本三斤在线观看 | 免费看大片a| 国产剧情av在线播放 | 中国国产bdsm紧缚捆绑 | 调教奶奴 | 欧美婷婷精品激情 | 黑丝一区二区三区 | 青青草国产一区 | 日韩高清成人 | 清纯唯美第一页 | 免费观看黄色一级片 | 日韩人妻精品无码一区二区三区 | 国产亚洲精品久久久久久青梅 | 日韩视频一区 | 另类视频在线观看 | 久久久久久久人妻无码中文字幕爆 | 亚洲国产精品成人综合在线 | 香蕉视频免费看 | 在线观看成人 | 亚洲美女视频在线 | 超碰伦理| 亚洲免费人成 | 成人免费淫片aa视频免费 | 欧美老女人性生活视频 | 亚洲一区二区免费在线观看 | 韩国精品一区二区三区 | 网站黄色在线观看 |