【C++】extern "C"詳解

来源:https://www.cnblogs.com/realHarvey/archive/2022/11/14/16888917.html
-Advertisement-
Play Games

先說結論 : extern "C"隻影響到鏈接期的name mangling 什麼是name mangling? 請看 : C++函數重載的實現機制之name mangling - 知乎 (zhihu.com) 舉個例子 : // external.h #ifdef __cplusplus exte ...


先說結論 :  extern "C"隻影響到鏈接期的name mangling

什麼是name mangling?

    請看 :  C++函數重載的實現機制之name mangling - 知乎 (zhihu.com)

舉個例子 :

// external.h
#ifdef __cplusplus
extern "C" {
#endif

void external();

#ifdef __cplusplus
}
#endif
// external.cc
#include "external.h"

template <typename T> // 這明顯是C++特性, gcc是無法編譯的
void external()
{
    T a;
}
// main.c
#include "external.h"

int main()
{
    external();
}

在這裡 : main函數裡面調用了c++函數external(), 如果這個函數沒被 extern "C"包裹, 會出現"undefined reference to"的錯誤.

這是因為g++、clang++都優先判斷尾碼名 ( 除非自己改option ), 就會對external.cc文件進行C++方式編譯 : 

  由於c++重載機制的存在, 編譯器只能在你命名之後 再悄悄重新給函數做個標記, 這個標記名也是有規則的, 比如g++, [ _Z + 函數名長度 + v / i ...標記符 ] .

  external()函數被compiler賦予一個"符號", 如果是gcc, 這個符號就是external;

                       如果是g++, 這個符號是 _Z8externalv 或者_Z8externali;

                            而clang++更誇張, 變成了"?external@@YAHXZ"或者"?external@@YAHH@Z"這種怪物.

然後把obj文件中定義和引用的global variable和function存到一張"符號表"中方便鏈接器的工作.

------------------------------------------------------------------------------------------------------------------

             名字             |               類型                |          是否可被外部引用            |             區域

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

      _Z8externalv     |           定義, 引用            |                       可                       |           代碼段

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

      _Z8externali      |           定義, 引用            |                       可                       |           代碼段

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    main            |               定義                 |                                                  |

-------------------------------------------------------------------------------------------------------------------

  鏈接器說"我開始找了 ! ", 然後給main函數找external(), 發現沒有c版本的, 只有c++版本的呀, 它幹不了了, "undefined reference to external".

  如果你把聲明extern "C",  鏈接器才能找到c版本的external(), 加上依賴庫/模塊 全打包起來. 還是拿gnu來說吧, c程式會打包libgcc.a靜態庫,c++程式則會打包很多libstdc++.a的東西和一些各式各樣的依賴, 這也是一般c++程式大小都要pure c大的原因, 在嵌入式平臺這種差距尤為明顯.

  人家卡馬喬也有話說的 : " 我找的是什麼表啊, 你這個表什麼都有 我都能找到為什麼不能鏈接? "

  c文件和c++文件直接鏈接在一起, 鏈接器應該用libgcc這個鏈子還是libstdc++呢?它沒法去判斷啊,只能你騙他一下這是c文件, 用libgcc去鏈.

 

所以, 你extern "C"包裹函數的聲明, 並不會改變函數體內語句的實際編譯方式, 因為它的定義仍在.cc文件里, g++仍會優先將它以c++的方式編譯. 但是函數名的確是以c的方式編去了.

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 5. 文件服務開發 全套代碼及資料全部完整提供,點此處下載 5.1 環境搭建 5.1.1 資料庫環境搭建 第一步:創建pd_files資料庫 create database pd_files character set utf8mb4; 第二步:在pd_files資料庫中創建pd_attachmen ...
  • 前提 Tomcat 10.1.x Tomcat線程池介紹 Tomcat線程池,源於JAVA JDK自帶線程池。由於JAVA JDK線程池策略,比較適合處理 CPU 密集型任務,但是對於 I/O 密集型任務,如資料庫查詢,rpc 請求調用等,不是很友好,所以Tomcat在其基礎上進行了擴展。 任務處理 ...
  • 模板 c++另一種編程思想稱為泛型編程,主要利用的技術就是模板 c++提供兩種模板機制:函數模板和類模板 函數模板 建立一個通用函數,函數的返回值類型和形參類型可以不具體指定,用一個虛擬的類型來代表 語法: template<typename T> //或者 template<class T> 函數 ...
  • 渲染模板 我的客服系統後端使用的golang Gin 框架,想把頁面渲染出來,下麵就是載入html模板頁面 package router func InitViewRouter(engine *gin.Engine) { //關於頁面 engine.GET("/aboutus.html", func ...
  • 在看集合源碼的時候,因為對一些知識點有些混淆,導致看源碼比較吃力。所以重新回顧一下麵向對象的繼承和多態,順便記錄一下重點。 繼承 子類會繼承父類的所有屬性和方法,但私有屬性和方法在子類不能直接訪問,需要通過父類提供的公共方法訪問; 子類必須調用父類的構造器,完成父類的初始化(創建子類對象時會調用父類 ...
  • 本文花了較短的篇幅重點介紹了JVM Sandbox的功能,實際用法,以及基礎原理。它通過封裝一些底層JVM控制的框架,使得對JVM層面的AOP開發變的異常簡單,就像作者自己所說“JVM-SANDBOX還能幫助你做很多很多,取決於你的腦洞有多大了。” ...
  • 本篇學習 Yarn Application 編寫方法,將帶你更清楚的瞭解一個任務是如何提交到 Yarn ,在運行中的交互和任務停止的過程。通過瞭解整個任務的運行流程,幫你更好的理解 Yarn 運作方式,出現問題時能更好的定位。 一、簡介 本篇將對 Yarn Application 編寫流程進行介紹。 ...
  • 數據結構是Python中一個很重要的概念,是以某種方式(如通過編號)組合起來的數據元素(如數字、字元乃至其他數據結構)的集合。 在Python中,最基本的數據結構是序列(sequence)。 序列中的每個元素都有編號,及其位置或索引,其中的第一個元素的索引為0,第二個元素位的索引為1,依此類推 在有 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...