【C與C++的相互調用方法】

C與C++的相互調用方法

  • C與C++為什么相互調用的方式不同
  • C++中調用C
  • C中調用C++
  • 致謝

C與C++為什么相互調用的方式不同

??C 和 C++ 之間的相互調用方式存在區別,主要是由于 C 和 C++ 語言本身的設計和特性不同。

  • 函數調用和參數傳遞方式不同:C 和 C++ 在函數調用和參數傳遞方面有一些不同之處。C 使用標準的函數調用約定,而 C++ 在函數調用中可能包含額外的信息,如函數重載和默認參數。為了正確匹配函數簽名,C++ 編譯器可能會在函數名上進行名稱修飾(name mangling)。
  • 函數重載和名稱修飾:C++ 支持函數重載,即可以有相同的函數名但不同的參數列表。為了在可執行文件中區分這些重載函數,C++ 編譯器會在函數名中添加一些信息,以便于重載解析。這與 C 的函數名約定不同,C 中函數名是平鋪的。
  • 鏈接庫的差異:C 和 C++ 編譯器鏈接不同的標準庫。C 編譯器鏈接 C 標準庫,而 C++ 編譯器鏈接 C++ 標準庫。由于標準庫可能涉及不同的函數和數據結構,因此在鏈接階段可能會有不同的處理。
  • 編譯器特性:C 和 C++ 編譯器對代碼的解析、優化、鏈接等可能會有不同的處理方式,這可能會導致在 C 和 C++ 相互調用時需要進行適當的處理。

??解決手段:為了在 C 和 C++ 之間實現相互調用,C++ 引入了 extern “C” 語法,它可以用來告訴 C++ 編譯器在函數聲明上使用 C 的調用約定,以便在鏈接階段能夠正確解析函數名。這種設計是為了在 C 和 C++ 之間實現互操作性,但由于兩者的語法和特性存在差異,因此在調用方式、編譯器行為和鏈接方式上會存在一些差異。

C++中調用C

??話不多說,直接上案例,下面是一個簡單的示例,演示了如何在 C++ 代碼中調用 C 函數:

首先分別創建三個文件:mylib.cmylib.hmain.cpp

??mylib.c如下:

// mylib.c
#include <stdio.h>void my_c_function() {printf("This is a C function.\n");
}

??mylib.h如下:

// mylib.h
#ifndef MYLIB_H
#define MYLIB_Hvoid my_c_function();#endif // MYLIB_H

??main.cpp如下:

// main.cpp
#include <iostream>extern "C" {// 聲明 C 函數的原型void my_c_function();
}int main() {std::cout << "Calling a C function from C++:" << std::endl;// 調用 C 函數my_c_function();return 0;
}

??在這個示例中,我們使用了 #include "mylib.h" 來引入頭文件,并在 C++ 中調用了 my_c_function()。這樣就能正確地在 C++ 中調用 C 函數。編譯步驟如下:

gcc -c mylib.c -o mylib.o   # 編譯 C 文件為目標文件
g++ -c main.cpp -o main.o   # 編譯 C++ 文件為目標文件
g++ main.o mylib.o -o app  # 鏈接目標文件生成可執行文件

??編譯后的文件列表如下:
在這里插入圖片描述
??然后運行可執行文件:./app得到輸出結果:
在這里插入圖片描述
??這里可以使用objdump命令查看編譯之后的中間文件mylib.omain.o的符號表:
在這里插入圖片描述
在這里插入圖片描述
??可以發現,my_c_function()函數編譯出的名稱在mylib.omain.o是相同。這是由于 C++ 文件中使用 extern “C” 來聲明 C 調用約定,以便 C 能夠正確解析函數名。
??我們來看看如果沒有使用extern “C” 后的編譯情況吧:
在這里插入圖片描述
??可以發現,不使用 extern “C”, 函數 my_c_function 編譯后名稱變為了 (_Z13my_c_functionv)
??是由于在C++中,函數名在編譯后會根據函數的參數類型和返回類型進行名稱重整(Name Mangling),以支持函數重載等特性。這是因為C++支持函數的參數類型和個數可以不同,所以需要在編譯后為每個函數生成一個唯一的名稱。
??當你在C++中調用一個C函數時,如果不使用 extern “C” 聲明,C++ 編譯器會默認對函數名進行名稱重整。而在C語言中,函數名不會被重整。
??如果你在C++中調用了一個C函數,并且沒有使用 extern “C” 聲明,C++ 編譯器會對函數名進行名稱重整,生成一個新的名字,類似 _Z13my_c_functionv 這樣的名稱。這個過程被稱為名稱重整(Name Mangling),是為了確保函數在C++中能夠正確處理函數重載等特性。

C中調用C++

??下面還是來看一個簡單的示例,演示了如何在 C 代碼中調用 C++ 函數:

首先分別創建三個文件:mylib.cppmylib.hmain.c

??mylib.cpp如下:

// mylib.cpp
#include <iostream>#include "mylib.h"void my_cpp_function(int num) {std::cout << "C++ function called with number: " << num << std::endl;
}

??mylib.h如下:

// mylib.h
#ifndef MYLIB_H
#define MYLIB_H#ifdef __cplusplus
extern "C" {
#endifvoid my_cpp_function(int num);#ifdef __cplusplus
}
#endif#endif // MYLIB_H#endif // MYLIB_H

??main.c如下:

// c_main.c
#include <stdio.h>#include "mylib.h"int main() {printf("Calling C++ function from C\n");// Call the C++ functionmy_cpp_function(42);return 0;
}

??在這個示例中,我們使用了 #include "mylib.h" 來引入頭文件,并在 main.c 中調用了 my_cpp_function()。這樣就能正確地在 C 中調用 C++ 函數。編譯步驟如下:

g++ -c mylib.cpp -o mylib.o   # 編譯 C 文件為目標文件
gcc -o main main.c mylib.o -lstdc++  # 鏈接目標文件生成可執行文件

注釋-lstdc++ 是用于鏈接 C++ 標準庫的編譯選項。在Linux系統中,C++ 標準庫通常被命名為 libstdc++.so,使用 -lstdc++ 編譯選項可以將這個庫鏈接到可執行文件中,以便在運行時使用C++的標準庫函數和功能。

??如果缺少 -lstdc++ 則會報錯:
在這里插入圖片描述
??編譯后的文件列表如下:
在這里插入圖片描述
??然后運行可執行文件:./main得到輸出結果:
在這里插入圖片描述
??這里解釋一下mylib.h頭文件中的 #ifdef __cplusplus:在main.c文件夾中調用mylib.h頭文件,但是 C 語言中并沒有 extern 這個關鍵字,因此,使用 #ifdef __cplusplus來充當一個譯時候的閥門。
??總結一下:對于C調用C++的情況,沒有 extern “C” 這樣的關鍵字。您需要在C++代碼中使用 extern “C” 來確保C++函數按照C的方式進行鏈接,同時在C代碼中包含相應的頭文件并調用這些函數。

致謝

??本文的學習參考了以下文章:C與C++如何互相調用

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/41635.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41635.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41635.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

docker oracle linux命令執行sql

docker 安裝參照 https://blog.csdn.net/arcsin_/article/details/123707618 docker container ls -a命令查看容器名 打開容器 docker exec -it orcl19c_03 /bin/bashsys 用戶登錄容器 sqlplus / as sysdbashow pdbs;什么是pdb數據庫&#xff1f;什么是CDB&#xff1f; 參…

游戲如何防御DDOS流量攻擊呢,用游戲盾真的有用么?

針對在線游戲行業來說&#xff0c;DDoS&#xff08;分布式拒絕服務&#xff09;攻擊是一種極具破壞性的威脅。DDoS攻擊可能導致游戲服務器不可用&#xff0c;嚴重影響游戲體驗和運營。為了解決這一問題&#xff0c;游戲盾作為一種專門為游戲行業設計的安全解決方案&#xff0c;…

微信小程序 藍牙設備連接,控制開關燈

1.前言 微信小程序中連接藍牙設備&#xff0c;信息寫入流程 1、檢測當前使用設備&#xff08;如自己的手機&#xff09;是否支持藍牙/藍牙開啟狀態 wx:openBluetoothAdapter({}) 2、如藍牙已開啟狀態&#xff0c;檢查藍牙適配器的狀態 wx.getBluetoothAdapterState({}) 3、添加…

第十三章 SpringBoot項目(總)

1.創建SpringBoot項目 1.1.設置編碼 1.4.導入已有的spring boot項目 2.快速搭建Restfull風格的項目 2.1.返回字符串 RestController public class IndexController {RequestMapping("/demo1")public Object demo1() {System.out.println("demo1 ran...."…

kafka的位移

文章目錄 概要消費位移__consumer_offsets主題位移提交 概要 本文主要總結kafka的位移是如何管理的&#xff0c;在broker端如何通過命令行查看到位移信息&#xff0c;并從代碼層面總結了位移的提交方式。 消費位移 對于 Kafka 中的分區而言&#xff0c;它的每條消息都有唯一…

0基礎學習VR全景平臺篇 第86篇:智慧眼-為什么要設置分組選擇?

一、功能說明 分組選擇&#xff0c;也就是給全景的每個分組去設置其所屬的行政區劃&#xff0c;設置后只有屬于同行政區劃的成員才可進入其場景進行相關操作&#xff0c;更便于實現城市的精細化管理。 二、后臺編輯界面 分組名稱&#xff1a;場景的分組名稱。 對應分類&…

網絡安全--linux下Nginx安裝以及docker驗證標簽漏洞

目錄 一、Nginx安裝 二、docker驗證標簽漏洞 一、Nginx安裝 1.首先創建Nginx的目錄并進入&#xff1a; mkdir /soft && mkdir /soft/nginx/cd /soft/nginx/ 2.下載Nginx的安裝包&#xff0c;可以通過FTP工具上傳離線環境包&#xff0c;也可通過wget命令在線獲取安裝包…

【數據結構與算法】隊列

文章目錄 一&#xff1a;隊列1.1 隊列的概念1.2 隊列的介紹1.3 隊列示意圖 二&#xff1a;數組模擬隊列2.1 介紹2.2 思路2.3 代碼實現2.3.1 定義隊列基本信息2.3.2 初始化隊列2.3.3 判斷隊列是否滿&#xff0c;是否為空2.3.4 添加數據到隊列2.3.5 獲取隊列數據&#xff0c;出隊…

垃圾回收機制

什么是內存泄漏&#xff1f; 內存泄漏是指程序中已經不再使用的內存卻沒有被正確釋放或回收的情況。在編程中&#xff0c;當對象或數據不再被程序使用&#xff0c;但其所占用的內存空間沒有被垃圾回收機制回收&#xff0c;就會導致內存泄漏。 內存泄漏可能會導致程序的內存消…

圖數據庫_Neo4j和SpringBoot整合使用_創建節點_刪除節點_創建關系_使用CQL操作圖譜---Neo4j圖數據庫工作筆記0009

首先需要引入依賴 springboot提供了一個spring data neo4j來操作 neo4j 可以看到它的架構 這個是下載下來的jar包來看看 有很多cypher對吧 可以看到就是通過封裝的驅動來操作graph database 然后開始弄一下 首先添加依賴

【實用黑科技】如何 把b站的緩存視頻弄到本地——數據恢復軟件WinHex 和 音視頻轉碼程序FFmpeg

&#x1f468;?&#x1f4bb;個人主頁&#xff1a;元宇宙-秩沅 &#x1f468;?&#x1f4bb; hallo 歡迎 點贊&#x1f44d; 收藏? 留言&#x1f4dd; 加關注?! &#x1f468;?&#x1f4bb; 本文由 秩沅 原創 &#x1f468;?&#x1f4bb; 收錄于專欄&#xff1a;效率…

onnxruntime 支持的所有后端

1 代碼導出 import onnxruntime as ort aaa ort.get_all_providers() print(aaa)1. 1 下面是ort支持的所有后端 TensorrtExecutionProvider, CUDAExecutionProvider, MIGraphXExecutionProvider, ROCMExecutionProvider, OpenVINOExecutionProvider, DnnlExecutionProvider…

Baumer工業相機堡盟工業相機如何通過BGAPISDK設置相機的固定幀率(C#)

Baumer工業相機堡盟工業相機如何通過BGAPI SDK設置相機的固定幀率&#xff08;C#&#xff09; Baumer工業相機Baumer工業相機的固定幀率功能的技術背景CameraExplorer如何查看相機固定幀率功能在BGAPI SDK里通過函數設置相機固定幀率 Baumer工業相機通過BGAPI SDK設置相機固定幀…

藍牙資訊|中國智能家居前景廣闊,藍牙Mesh照明持續火爆

據俄羅斯衛星通訊社報道&#xff0c;中國已成為全球最大的智能家居消費國&#xff0c;占全球50%—60%的市場份額。未來&#xff0c;隨著人工智能技術的發展以及智能家居生態的不斷進步&#xff0c;智能家居在中國的滲透率將加速提升。德國斯塔蒂斯塔調查公司數據顯示&#xff0…

win10系統docker創建ubuntu容器解決開發環境問題

一、win10系統使用docker的原因 最近啊&#xff0c;在學習人工智能-深度學習&#xff0c;用的win10系統進行開發&#xff0c;老是出現一些莫名其妙的問題&#xff0c;無法解決&#xff0c;每天都在為環境問題搞得傷透了腦筋。 說到底還是要使用Linux系統進行開發比較合適。 …

【MT32F006】MT32F006之HT1628驅動LED

本文最后修改時間&#xff1a;2023年03月30日 一、本節簡介 本文介紹如何使用MT32F006連接HT1628芯片驅動LED。 二、實驗平臺 庫版本&#xff1a;V1.0.0 編譯軟件&#xff1a;MDK5.37 硬件平臺&#xff1a;MT32F006開發板&#xff08;主芯片MT32F006&#xff09; 仿真器&a…

LeetCode算法心得——限制條件下元素之間的最小絕對差(TreeSet)

大家好&#xff0c;我是晴天學長&#xff0c;今天用到了Java一個非常實用的類TreeSet&#xff0c;能解決一些看起來棘手的問題。 1 &#xff09;限制條件下元素之間的最小絕對差 2) .算法思路 初始化變量&#xff1a;n為列表nums的大小。 min為整型最大值&#xff0c;用于記錄…

python3 0學習筆記之基本知識

0基礎學習筆記之基礎知識 &#x1f4da; 基礎內容1. 條件語句 if - elif - else2. 錯誤鋪捉try - except(一種保險策略&#xff09;3. 四種開發模式4. 函數&#xff1a;def用來定義函數的5. 最大值最小值函數&#xff0c;max &#xff0c;min6. is 嚴格的相等&#xff0c;is no…

機器學習:基本介紹

機器學習介紹 Hnad-crafted rules Hand-crafted rules&#xff0c;叫做人設定的規則。那假設今天要設計一個機器人&#xff0c;可以幫忙打開或關掉音樂&#xff0c;那做法可能是這樣&#xff1a; 設立一條規則&#xff0c;就是寫一段程序。如果輸入的句子里面看到**“turn of…

C#__使用Type類反射數據的基本用法

// 簡單介紹 // 元數據&#xff08;metadata&#xff09;&#xff1a;與程序及其類型有關的數據。 // 反射&#xff1a;一個運行的程序查看本身元數據或其他程序集中的元數據的行為 // Assembly類&#xff1a;允許訪問給定程序集的元數據&#xff0c;包含了可以加載和執行程序…