2012-05-31 71 views
1

我嘗試在從++庫已經最初設計與結構繼承一個C接收到的C程序的數據訪問:如何在C中映射繼承的C++結構體?

例如:

// C++ data structures 
typedef struct _Base 
{ 
public: 
    int id; 
    wchar_t* name; 
} Base; 


typedef struct _Struct1 : Base 
{ 
public: 
    int valueCount; 
} Struct1; 


typedef struct _Struct2 : Base 
{ 
public: 
    int parentID; 
    int amount; 
} Struct2; 

我使用以下數據結構中下映射試過。

typedef struct _Base 
{ 
    int id; 
    wchar_t* name; 
} Base; 


typedef struct _Struct1 
{ 
    // Base struct data 
    int id; 
    wchar_t* name; 

    int valueCount; 
} Struct1; 


typedef struct _Struct2 
{ 
    // Base struct data 
    int id; 
    wchar_t* name; 

    int parentID; 
    int amount; 
} Struct2; 

但是打印數據,它看起來像我得到錯誤的值。

我是否缺少一些關於C++如何在內部表示繼承結構的參考?

在此先感謝!

+1

哪些值是錯誤的?請更具體一些。 – Matt

+0

您是否在使用Visual Studio等集成開發環境?如果你可以調試代碼,也許你的工具將允許你查看你正在接收的內存的原始字節,並且你可以計算出與你的期望不符的內容。 –

+0

@Patrick:你能修改C++代碼嗎? –

回答

3

的C++ 11規則上的POD(What are Aggregates and PODs and how/why are they special?指定不允許混合具體基類與數據成員,但實際上對於大多數具有單個POD基類的編譯器而言,等同於將該類封裝爲第一個成員。

嘗試指定的C結構封裝基座結構:

typedef struct _Struct1 
{ 
    Base base; 
    int valueCount; 
} Struct1; 

注意的是,如果C++類是非POD(例如具有虛擬方法),這將不起作用。

+0

我想過這樣做,但在API方面,它並不真正通過base和valueCount直接訪問某些屬性是有意義的。 –

+0

封裝結構在內部表示方面是否有所不同? –

+0

它不應該真的有所作爲,但它是一個開始的地方。你確定指針的大小和wchar_t在你的平臺之間的長度相同嗎? – ecatmur

0

您可以嘗試在您正在使用的C++庫上使用包裝器層將來自C++的值輸出到C,而不是直接使用來自C++端的內容。如果來自額外層的開銷不會很大,那可能會有效。

投射一個C++類可能不總是工作,因爲它保持類結構內的成員和虛方法指針。

2

您可能會欺騙您的C編譯器生成一個具有相同內存佈局的C++類的結構,並且在很多情況下都可以工作,但這是一個相當不穩固的基礎。

可移植的方式是編寫存取器函數。一定要將它們聲明爲extern "C"

爲一個標題文件說明性示例(不一定乾淨;在網絡形式的寫代碼典型地告誡:-)):

#ifdef __cplusplus 

// C++ declarations go here 

class Foo 
{ 
public: 
    int bar; 
}; 

// C calling conventions follow 

extern "C" { 

#else 

// Make it so your C code can work with Foo* as an incomplete/not-dereferencable 
// type. 
typedef void Foo; 

#endif 

// Declare this in a C++ source file to return fooptr->bar 
int foo_get_bar(Foo *fooptr); 

#ifdef __cplusplus 
} // extern "C" 
#endif 
+0

無法更改C++源代碼,只有頭文件作爲參考。 –

+0

@PatrickAllaert - 請參閱更多以瞭解含義,而不是「我可以複製和粘貼什麼?」模式。我不是主張更改C++源代碼,只是展示一種技術。如果這個類在另一個頭部,用正確的'#inc'替換「'Foo {/ * ... * /};'」。關鍵是你寫自己的'foo_get_bar()'這是一個可從C調用的C++函數。 – asveikau

+0

好吧,知道了,對不起:) –

1

調查的一種可能性是您定義的結構是正確的,但編譯器使用的對齊方式不匹配。請參閱:

http://en.wikipedia.org/wiki/Data_structure_alignment

通常你可以使用編譯器開關或#pragma指令設置對齊。您必須閱讀您的編譯器文檔才能瞭解相關信息。如果您無法聯繫C++代碼的作者,您可能需要使用調試器來查看您接收的原始內存,以確定結構中不同值之間的對齊/填充。

如果一個程序編譯爲64位機器,另一個編譯爲32位機器,則可能會出現此類問題。或者可以歸結爲不同的編譯器實現。