簡體   English   中英

將C ++結構傳遞給期望C結構的庫

[英]Passing C++ struct to library expecting C struct

我正在Linux中編寫一個C ++程序,需要使用用C編寫的舊庫。庫使用C結構將信息傳入和傳出函數,這些結構是字節對齊的(無填充)。

我的理解是C ++中的結構實際上是一個對象,而C中的結構只是一個內存塊,被分成可單獨尋址的部分。

如何在C ++中創建C樣式結構以傳遞給庫? (我不能傳遞一個對象)

你在這里問兩個問題,真的......

如何在C ++中創建C樣式結構?

代替

struct foo { /* ... */ };

使用

extern "C" {
    struct foo { /* ... */ };
}

這可能不會導致任何不同,即“C ++樣式結構”和“C樣式結構”通常是相同的,只要您不添加方法,受保護的成員和位字段。 但是,由於函數需要“extern C”,所以在這些大括號中包含所有用於C的代碼是合理的。

有關更多詳細信息,請參閱: 外部“C”在C ++中的作用是什么? 和@AndrewHenle的評論。


我...需要使用用C編寫的庫

我在這里解釋一個正式的C ++ FAQ項目 ,告訴你(驚訝,驚訝)只是在一個extern C塊中包含庫頭,然后像你編寫C一樣使用它中的任何內容:

extern "C" {
  // Get declaration for `struct foo` and for `void f(struct foo)`
  #include "my_c_lib.h"
}

int main() {
    struct foo { /* initialization */ } my_foo;
    f(my_foo);
}

我的理解是C ++中的結構實際上是一個對象,而C中的結構只是一個內存塊,被分成可單獨尋址的部分。

你剛才用不同的詞語描述了幾乎完全相同的東西。

由於兩種語言的語法重疊,您通常可以使用struct關鍵字定義的簡單類,並使用C編譯器編譯相同的定義。

此外,您通常可以將指向用戶定義類型的對象的指針從C ++程序傳遞到C程序。 但是,您通常希望將該定義包裝在extern "C"中,以便告訴計算機您希望這種兼容性。

最后,請記住,在C ++中,關鍵字class和關鍵字struct都引入了一個類定義,因此C ++實際上沒有“結構”,但在C中它們絕對是一個東西(而類不是)。 因此,只需要小心使用術語。

所以,這個問題有一些與之相關的復雜問題。 但是,對於第一個近似,答案很簡單。

C編譯器和C ++編譯器(大多數C編譯器都接受它們)將接受的任何C struct聲明都將是“ 標准布局類型 ”。 這是C ++標准中定義的概念,C ++編譯器應該以某種方式對待它們。

特別是,符合C ++編譯器符合的ABI(也稱為應用程序二進制接口)子集的C編譯器應具有與此類型完全相同的內存表示。

對於Linux和Windows,ABI都經過了C和C ++的精心定義,現在已經有5到10年了。 任何平台上的所有編譯器都應該符合它。 所以對於任何常見的C和C ++編譯器組合都是如此。 這包括Clang,g ++,Visual Studio,基本上幾乎任何在該平台上都不具備高度專業性的編譯器。 這並不一定意味着標准C ++庫的不同版本具有兼容的實現,因為(例如)多年來實現::std::string的方式(因此字符串結構中實際存在哪些數據)盡管公共界面沒有太大變化,但已經發生了巨大的變化。

C ++ ABI由於一些不同的因素而變得復雜。 其中包括異常處理和函數名稱修改(在函數的鏈接器符號名稱中編碼函數參數的類型)約定。 此外,由於在很多情況下和其他問題中類型默認為int的方式,C很大程度上要求調用者在函數完成后從堆棧中彈出參數,因為被調用的函數無法確定參數的大小已經被推上了。 C ++有更嚴格的類型檢查,有一段時間這導致了一個'被調用函數彈出參數'調用約定。 我認為不再是這種情況了,因為我認為它的效率較低。 我可能錯了。

現在,如果您開始使用編譯器特定的關鍵字,如'packed'或'aligned',這一切都會消失。 然后,您應該仔細查閱文檔以了解會發生什么。

人們提到了一個extern "C"聲明。 這些對於C和C ++代碼之間的接口很重要,但它們與struct布局無關,根本不需要它。 什么extern "C"聲明是好的,聲明函數名稱和調用約定符合C ABI而不是C ++ ABI。 這是關於調用者是否從堆棧或被調用函數中彈出函數調用參數,函數名稱如何變為符號以供鏈接器使用,訂單參數被推入堆棧,等等。 同樣,關於結構如何在內存中布局的內容與extern "C"無關。 該構造完全是關於函數,而不是struct

並且,為了重新迭代,這里有很多復雜性。 但在絕大多數情況下,您根本不需要擔心它。 它會起作用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM