2016-04-26 74 views
12

我有一個超過10年的C庫 - 我相信 - 在過去的美好時光裏工作得很好,但是當我試圖在C++源代碼中使用它時(包含主函數)遇到了一些困難。如何使用C++將舊C代碼與保留關鍵字相關聯?

編輯:爲了澄清,C庫編譯得很好,用gcc,它生成一個目標文件old_c_library.o。這個庫應該以某種方式使用,以便您的main.c C源文件中的C頭文件old_c_library.h#included。然後,您的主C源文件應該編譯並通過與old_c_library.o鏈接在一起。在這裏,我想使用C++源文件main.cpp來代替,並使用g++進行編譯/鏈接。發生

以下三個問題,C++源文件的編譯過程中:

  1. C庫的頭文件中的一個包含所述C++保留字new(它是一個整數的名稱),導致致命錯誤;和
  2. C庫的其中一個頭文件包含calloc調用(缺少明確的類型轉換),導致致命錯誤;和
  3. C庫的各種文件包含代碼,其中發生了帶符號和無符號整數的比較,從而導致警告。

編輯:我試圖使用#extern "C" { #include "obsolete_c_library.h" }「竅門」,正如評論中所建議的那樣,但這並沒有解決我的任何問題。

我可以通過重命名保留字的所有實例並將其替換爲 - 基本上 - 其他任何內容來解決問題1。我可以通過調用calloc調用來解決問題2。我可能會嘗試通過此處提出的建議來解決警告:How to disable GCC warnings for a few lines of code

但我仍然想知道,有沒有辦法以優雅,高級的方式克服這些困難,沒有實際上觸摸原始圖書館?


相關: Where is C not a subset of C++?Do I cast the result of malloc?How do I use extern to share variables between source files?

+1

在包含使用'new'作爲變量名稱的標題後,您可以在之前放置一個'#define new old',並在'#undef new'處輸入 – user463035818

+3

如果關鍵字問題僅出現在舊庫的實現中不是它的API),爲什麼不單獨編譯並且只將它鏈接到C++項目中? – nils

+2

唯一的優雅方式可能是更新庫。一旦你被要求讓代碼腐爛,優雅就會消失,你將不得不使用任何骯髒的黑客來完成工作。 – ComicSansMS

回答

1

一般來說,如果這些頭文件不是爲了預期這種用法而構建的,那麼將C頭文件保存到C++源文件中並不安全。在某些情況下可以開始工作,但是您需要準備好修改頭文件或爲要訪問的函數和全局變量編寫自己的聲明。

至少,如果C頭文件聲明瞭任何函數,並且您沒有在C++中重新編譯這些函數,那麼您必須確保聲明在您的C++代碼中被分配了C連接。它的情況並不少見C頭文件通過條件編譯指令自動考慮這一點,但如果他們不這樣做,那麼你可以通過在C鏈接塊包裹包含(S)做它的另一面:

extern "C" { 
#include "myclib.h" 
} 

如果C頭文件中聲明的全局變量的名字衝突C++的關鍵字,,哪些是你不需要引用,那麼你可能能夠使用預處理器重新定義它們:

#define new extern_new 
#include "myclib.h" 
#undef new 

這並不能保證工作,但值得一試。如圖所示,在包含C頭後,請不要忘記#undef這樣的宏。

可能還有其他一些有趣的技巧可以用宏來調整特定的頭文件到C++中,但是在某些時候,只需複製/重寫所需的聲明(並且僅限於那些)或者在你自己的C++頭文件中。請注意,這樣做並不會取消聲明C鏈接的需要 - 該要求來自於由C編譯器而不是C++編譯器編譯的庫。

2
  1. 您可以寫一個c頭的副本,唯一的區別是缺少聲明extern int new。然後使用新創建的C++友好標題而不是舊的不兼容標題。

    如果你需要從C++引用該變量,那麼你需要做一些更復雜的事情。您將需要在c中編寫一個新的包裝庫,該文件公開了 讀寫函數 指向C++的指針,該指針可用於訪問不幸命名的變量。

    如果某些內聯函數引用了變量,那麼您可以將它們從重複頭文件中刪除,如果需要從C++調用它們,請以C++友好方式重新實現它們。只要不要在extern "C"內重新實現相同的名稱,因爲這會使您與原有的內聯函數發生衝突,這些內聯函數可能由一些現有的c代碼使用。

  2. 做與1中所述相同的頭重複,省去有問題的內聯函數並在需要時重新實現。

  3. 如您所知,可以忽略或禁用警告。無需修改原始標題。您可以用不會產生警告的版本重寫任何{const,type} - 不安全的內聯函數,但是您必須考慮您的時間是否值得。

這種方法的缺點是你現在有一些/所有標題的兩個vesions。 C++使用的新的和舊的代碼可能使用的舊的。


如果你可以放棄不觸及原有庫的要求,不需要與現有編譯的二進制工作,然後一個優雅的解決辦法是簡單地重命名有問題的變量(1)。使非C++兼容的內聯函數(2.)非內聯並將它們移動到c源文件中。修復生成警告的不安全代碼(3.),或者如果警告是特定於C++的,則只需使函數非內聯。

+0

好的,我回想起這是一個「連接」問題,正如很多評論指出的那樣。消化所有這些可能需要一些時間。正如我所想的,如果可能,最優雅的方式是更新生鏽的庫。 – Matsmath