混合編譯:c++檔案呼叫c檔案變數和函式、c檔案呼叫c++檔案變數和函式
1.c++檔案呼叫c檔案變數和函式
前言:以前見到extern "C"這樣的語句,只是簡單地知道跟外部連結有關,但是沒有深刻理解它的意思。
首先,為什麼要使用extern "C"修飾符?
C++呼叫其它語言的函式,由於編譯器生成函式的機制不一樣,所以需要經過特殊處理,才可以呼叫。呼叫C語言的函式,需要在函式宣告的地方語句extern "C"。如果不使用該語句,在連結的時候,編譯器就會報以下這種錯誤。
Test.obj : error LNK2019: 無法解析的外部符號 "void __cdecl DeleteStack(struct _Node *)" ([email protected]
然後是如何使用?
應該怎麼使用該語句呢?
剛開始,我簡單地在C++原始檔的前面使用該語句宣告,但是還是出錯,而且是在編譯階段就報錯。
- error C2732: 連結規範與“DeleteStack”的早期規範衝突。
為什麼會出現這個錯誤呢?因為C++原始檔已經引入了C的標頭檔案,在標頭檔案裡,宣告該函式時沒有extern修飾,而這裡有extern修飾,所以衝突了。解決的辦法有兩個。
一。在C標頭檔案中加上extern修飾符。
直接加,也不行。因為C原始檔也包含了這個標頭檔案,當編譯C原始檔時,就會出現錯誤。所以,需要一種機制來區分是編譯C還是C++檔案。方法如下:
- #ifdef __cplusplus
- extern"C"
- #endif
- void DeleteStack(Stack stack);
因為在編譯C++檔案時,自動定義前處理器名字__cplusplus,而編譯C時,沒有該處理器名字。所以只有編譯C++時,才有符號extern “C”。
此外,連結指示extern "C"有單個和複合兩種形式。以上為單個形式,複合形式可以同時將幾個函式宣告為extern "C"
- extern"C" {
- void DeleteStack(Stack stack);
- void PrintStack(Stack stack);
- void Pop(Stack stack);
- }
加上前處理器名字如下:
- #ifdef __cplusplus
- extern"C" {
- #endif
- void DeleteStack(Stack stack);
- void PrintStack(Stack stack);
- void Pop(Stack stack);
- #ifdef __cplusplus
- }
- #endif
二。編寫一個C++風格的標頭檔案,在這裡新增extern修飾符。
使用方法一,很簡單。但是如果該標頭檔案是別人寫好,你無法修改。這個時候就要使用其它方法了。方法是定義C++自己的標頭檔案,檔名為"CStack.h"
- // CStack.h
- extern"C" {
- #include "Stack.h";
- }
2.c檔案呼叫c++檔案變數和函式
//xxx.cpp
#ifdef __cplusplus
extern "C" {
#endif
int ignore_raw_data;
#ifdef __cplusplus
}
#endif
//xxx.c
extern int ignore_raw_data;
3.綜合使用
一般我們都將函式宣告放在標頭檔案,當我們的函式有可能被C或C++使用時,但我們無法確定函式是在c還是cpp裡面被定義(cxx都算,如蘋果是mm,google是cc),也就無法確定是否要將函式宣告在extern "C"裡,所以,我們應該新增
xxx.h
- #ifdef __cplusplus
- extern"C"
- {
- #endif
- //函式宣告
- #ifdef __cplusplus
- }
- #endif
如果我們注意到,很多標頭檔案都有這樣的用法,比如string.h,等等。
- //test.h
- #ifdef __cplusplus
- #include <iostream>
- usingnamespace std;
- extern"C"
- {
- #endif
- void mytest();
- #ifdef __cplusplus
- }
- #endif
這樣,可以將mytest()的實現放在.c或者.cpp檔案中,可以在.c或者.cpp檔案中include "test.h"後使用標頭檔案裡面的函式,而不會出現編譯錯誤。一般情況下,只需要把_cpluscplus和extern "C"的關鍵字放到h檔案就行了,c檔案和cpp檔案包含這個標頭檔案,而不需要在加入這兩個關鍵字,以下是特殊情況,因為cout不能再c裡面用。
- //test.c或者test.cpp
- #include "test.h"
- void mytest()
- {
- #ifdef __cplusplus
- cout << "cout mytest extern ok " << endl;
- #else
- printf("printf mytest extern ok n");
- #endif
- }
- //main.cpp
- #include "test.h"
- int main()
- {
- mytest();
- return 0;
- }
總之,以後再見到這樣的用法就不要大驚小怪了。
參考:
http://blog.csdn.net/u012234115/article/details/43272441
http://bbs.csdn.net/topics/380061545
http://www.cnblogs.com/rollenholt/archive/2012/03/20/2409046.html
相關推薦
混合編譯:c++檔案呼叫c檔案變數和函式、c檔案呼叫c++檔案變數和函式
1.c++檔案呼叫c檔案變數和函式 前言:以前見到extern "C"這樣的語句,只是簡單地知道跟外部連結有關,但是沒有深刻理解它的意思。 首先,為什麼要使用extern "C"修飾符? C++呼叫其它語言的函式,由於編譯器生成函式的機制不一樣,所以需要經過特殊處理,才可以
MATLAB和C++編譯器混合編譯:Xcode 8的不相容錯誤
最近在看tracking方面的論文和程式碼,發現大多數都是用matlab和c++混合編譯的。對於linux和windows這兩個系統,暫時還沒有碰到編譯器不相容的問題,但是mac上面卻有問題,在命令列裡輸入: mex -setup 會有下面的錯誤提示:
C語言基礎: 浮點數轉化整數(向上取整、向下取整)| 求絕對值函式
Objective-C拓展了C,自然很多用法是和C一致的。比如浮點數轉化成整數,就有以下四種情況。 1.簡單粗暴,直接轉化 float f = 1.5; int a;a = (int)f; NSLog("a = %d",a); 輸出結果是1。(int)是強制型別轉化,丟棄浮點數的小數部分。
C++的拷貝建構函式、operator=運算子過載,深拷貝和淺拷貝、explicit關鍵字
1、在C++編碼過程中,類的建立十分頻繁。 簡單的功能,當然不用考慮太多,但是從進一步深刻理解C++的內涵,類的結構和用法,編寫更好的程式碼的角度去考慮,我們就需要用到標題所提到的這些內容。 最近,在看單例模式,覺得十分有趣,然而如果想要掌握單例模式,就必須掌握這些內容。下
手把手教你用 Spring Boot搭建一個線上檔案預覽系統!支援ppt、doc等多種型別檔案預覽
> 昨晚搭建環境都花了好一會時間,主要在浪費在了安裝 openoffice 這個依賴環境上(_Mac 需要手動安裝_)。 > > 然後,又一步一步功能演示,記錄,除錯專案,並且簡單研究了一下核心程式碼之後才把這篇文章寫完。 > > 另外,這篇文章我還會簡單分析一下專案核心程式碼。
Python函式的定義、匿名函式、函式的引數、函式呼叫、引數傳遞、變數作用域、遞迴呼叫
Python函式: 函式是組織好的,可重複使用的,用來實現單一,或相關聯功能的程式碼段。 Python提供了許多內建函式,比如print()。你也可以自己建立函式,這被叫做使用者自定義函式。 定義函式: 在Python中,定義一個函式要使用def語句,依次寫出函式名、
(23)物件呼叫非靜態方法執行過程、靜態方法呼叫記憶體執行過程
public class Person{ private String name; private int age; private static String country="cn
機器學習練習記錄(1):偽逆法、勢函式、基於二次準則的H-K函式、感知器法
勢函式的構造是人工勢場方法中的關鍵問題,典型的勢函式構造方法:P(θ)=f{d(θ,θ0),[dR(θ),O],dT}(1),式中 θ,θ0——機器人當前位姿與目標位姿向量;d(θ,θ0)——θ與θ0間的某種廣義距離函式;dR(θ),O——當前位姿下機器人與障礙物間的最小距離;dT——給定的門限值;P(θ)
執行緒順序控制:四個執行緒A、B、C、D向四個檔案寫入資料。要求A執行緒只寫入A,B執行緒只寫入B……
四個執行緒A、B、C、D向四個檔案寫入資料。要求A執行緒只寫入A,B執行緒只寫入B…… 最終達到的效果: A.txt內容為: A B C D &nbs
C語言__預處理(巨集定義、檔案包含、條件編譯)
C語言__預處理(巨集定義、檔案包含、條件編譯) 預處理簡單理解 1.C語言在對源程式進行編譯之前,會先對一些特殊的預處理指令作解釋(比如之前使用的#include檔案包含指令),產生一個新的源程式(這個過程稱為編譯預處理),之後再進行通常的編譯
C++使用static的錯誤:無法解析的外部符號、“static”不應在檔案範圍內定義的成員函式上使用 .
當將類的某個資料成員宣告為static時,該靜態資料成員只能被定義一次,而且要被同類的所有物件共享。各個物件都擁有類中每一個普通資料成員的副本,但靜態資料成員只有一個例項存在,與定義了多少類物件無關。靜態方法就是與該類相關的,是類的一種行為,而不是與該類的例項物件相關。 靜態資料成員的用途之一
c++11 條款22:當使用Pimpl(指向實現的指標)時,在實現檔案裡定義特定的成員函式
條款22:當使用Pimpl(指向實現的指標)時,在實現檔案裡定義特定的成員函式 假如你曾經和過多的編譯構建時間抗爭過,你應該熟悉Pimpl(指向實現的指標)這個術語。這項技術是你可以把類的資料成員替換成一個指向實現類(結構)的指標,把原來在主類中的資料成員
16bit C & ASM 如何混合編譯?
.exe 資料 bit urb 價值 nmake 開發 include 生成 起源: 今天在看以前沒看完的一本書《圖形程序開發人員指南》,在做裏面的例子。 第一章就出問題了,一個例子“L1_2.c, L1_3.asm" ,這是C程序和ASM匯編程序的混合編譯
Java編譯(二) Java前端編譯:Java原始碼編譯成Class檔案的過程
Java編譯(二)Java前端編譯: Java原始碼編譯成Class檔案的過程 在上篇文章《Java三種編譯方式:前端編
Windows遍歷全盤所搜檔案,並通過多執行緒顯示搜尋進度(C++/C)
程式設計軟體,系統 軟體:VS2017 工程屬性:MFC對話方塊(其他工程屬性稍作修改也適用) 系統:windows10家庭版 主要思想 1、利用CFileFind實現查詢檔案 2、利用遞迴實現全盤搜尋 3、多執行緒實現父對話方塊搜尋檔案時,子對話方塊顯示搜尋進度 軟體執行效
c++與matlab混合編譯———讀取mxArray內容
mxArray作為一種特殊且複雜的資料結構,需要通過matrix.h提供的相關介面去訪問。在混合編譯過程中,matlab變數以mxArray形式儲存,通常用mxArray* 型別來指定matlab工作空間變數的地
CPP檔案和C檔案混編和將sqlite3加入自己的c++工程
今天嘗試將使用sqlite3資料庫,直接使用sqlite3的原始碼,得到sqlite3.c和sqlite3.h。 我想將他們加入到我的cpp工程裡面 所以我新建了一個mysqlite3.cpp檔案,在裡面呼叫了sqlite3的函式。 下面來說明我遇到的問題及解決方法 一共有兩種編譯方
C++:函式的過載、inline函式、C/C++相互呼叫
一、過載(overloading) :函式名字相同,而引數不同。返回型別可以相同也可以不同。 若有題目為:實現兩個數相加,一般我們都會想到如下程式碼: int Sum(int a,int b) { return a
C# 將圖片匯出Excel(包括 建立Excel 、檔案壓縮、遞迴刪除檔案及資料夾)
新增引用 using ICSharpCode.SharpZipLib.Zip; public void CreateDirectory(string DirectoryPath) { if (!Directory.Exist
C# 用Linq的方式實現對Xml檔案的基本操作(建立xml檔案、增刪改查xml檔案節點資訊)
1 private static void GetXmlNodeInforOld( string xmlPath) 2 { 3 try 4 { 5