作者tinlans ( )
看板C_and_CPP
標題Re: [問題] 如何在C code裡include C++的class
時間Sat Nov 7 22:26:38 2009
※ 引述《Rx400 (American Dream)》之銘言:
: 自己寫了一個C++程式,已經測試過,
: 但是學長要求要把我寫的C++整合到C裡面,
: 我寫的C++都是用OO去寫,還用了stl,
: 我試著在class用extern "C"包起來,再寫個簡單的C,把c++的header檔引進來
: 但compile一下就掛了
: 請問有相關的資料可以參考嗎?
: 或者是要把所有的class改寫成struct?
因為你用到 OO,
所以我假定你的 class 裡面有 virtual 成員。
這樣 struct 搭 #ifdef __cplusplus 去隔開 member function 的方法就會不能用了,
因為必須是 POD 才能跟 C 的 struct 有相同的 layout。
不過還是有一種傳統的方法可以用。
假設你的 class 是:
class MyClass {
public:
virtual void foo();
virtual MyClass *bar(int var);
...
private:
...
};
你可以造出一個給 C 用的 header file 像是這樣:
struct MyClass; // C/C++ 只要有前置宣告就能用它的 pointer
#ifdef __cplusplus
extern "C" {
#endif
void foo(struct MyClass *obj);
struct MyClass *bar(struct MyClass *obj, int var);
...
#ifdef __cplusplus
}
#endif
然後開一個 C++ source file 檔去寫上面 foo 和 bar 的實作
(這個檔因為是 C++ source file 所以當然可以看到 class 定義式):
extern "C" void foo(struct MyClass *obj)
{
obj->foo();
}
extern "C" struct MyClass *bar(struct MyClass *obj, int var)
{
return obj->bar(var);
}
...
這樣 C program 就不需要看到 struct MyClass 的定義式。
它們的 object files 也能互相 link。
不過 linker 一定要是 C++ mode (GCC 的話就是下 g++ 而不是 gcc),
而且有 main() 的那個檔案最好用 C++ mode 編譯,
因為某些 compiler 可能會放一些 C++ 特有的啟動和結束碼在 main() 開頭跟結尾。
像是 global object (如 cin/cout 這些東西) 的初始化動作,
你用 C mode 的話就算有 link 到 C++ lib (如 libstdc++.so) 也未必會 work。
main() 如果真的只能用 C compiler 編過的話,
那也很簡單就直接把它改名如 legacy_main(),
然後你開一個 C++ source file 寫一個空的 main() 去 call 它就好了。
其實這種避免 C 看到 class 定義式的技巧很早就有了。
它在純 C 的年代就很流行,
因為純 C 年代的工程師就已經有封裝的觀念了。
常常會有不希望 struct 的內部結構被人知道太多的需求出現,
team work 的話甚至防範的對象還包括自己的同事。
當時的做法就是直接把 struct 定義式塞在 .c 或是不會公開的 .h 檔內,
這樣別人就沒辦法直接存取你 struct 變數裡的成員,
只能用你提供的 functions 去使用這個 struct
藉此達成封裝和資訊隱藏的目的。
--
Ling-hua Tseng (
[email protected])
Department of Computer Science, National Tsing-Hua University
Interesting: C++, Compiler, PL/PD, OS, VM, Large-scale software design
Researching: Software pipelining for VLIW architectures
Homepage:
https://www.tinlans.org
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 118.160.116.129
※ 編輯: tinlans 來自: 118.160.116.129 (11/07 22:29)
推 elfkiller:頭推 11/07 22:39
推 remmurds:推推推 11/07 22:44
→ remmurds:不過原PO在看完這篇後可能會覺得不如把class改成struct 11/07 22:47
→ remmurds:還比較快吧-.-" 11/07 22:47
推 Rx400:同一個研究所的等級怎嚜會那麼多,謝謝指教 11/07 23:00
推 QQ29:看T大的個人網頁 超威的 = = 11/07 23:02
→ awashharp:個人網頁被Firefox擋住了…憑證… 11/07 23:35
推 VictorTom:推一下....:) 11/08 00:15
→ tinlans:class -> struct 是必須的,但有 virtual function 的話, 11/08 03:02
→ tinlans:layout 跟 C 未必會通,因為有藏一個 vptr,你不能假設它 11/08 03:03
→ tinlans:在物件資料區段的開頭還是結尾或任何地方。 11/08 03:03
推 kikiqqp:推 這作法好 11/08 10:07
推 kkc:T大真的很威! 11/08 21:50
推 saxontai:推! 11/09 01:47
推 james732:很強大的分享,推!! 11/09 01:51
推 revivalworld:推 11/09 12:36
推 HudsonE:我看到很懷念的 MudOS... 11/09 16:28
推 hubert100:t大的老闆是我大學老師的老闆 11/10 12:46
推 theee:T大和我同鄉,第一次看到同鄉 XD 11/19 23:52
※ 編輯: tinlans 來自: 118.160.106.161 (11/22 13:03)