Re: [問題] 如何在C code裡include C++的class
※ 引述《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 (uranus@tinlans.org)
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)
推
11/07 22:39, , 1F
11/07 22:39, 1F
推
11/07 22:44, , 2F
11/07 22:44, 2F
→
11/07 22:47, , 3F
11/07 22:47, 3F
→
11/07 22:47, , 4F
11/07 22:47, 4F
推
11/07 23:00, , 5F
11/07 23:00, 5F
推
11/07 23:02, , 6F
11/07 23:02, 6F
→
11/07 23:35, , 7F
11/07 23:35, 7F
推
11/08 00:15, , 8F
11/08 00:15, 8F
→
11/08 03:02, , 9F
11/08 03:02, 9F
→
11/08 03:03, , 10F
11/08 03:03, 10F
→
11/08 03:03, , 11F
11/08 03:03, 11F
推
11/08 10:07, , 12F
11/08 10:07, 12F
推
11/08 21:50, , 13F
11/08 21:50, 13F
推
11/09 01:47, , 14F
11/09 01:47, 14F
推
11/09 01:51, , 15F
11/09 01:51, 15F
推
11/09 12:36, , 16F
11/09 12:36, 16F
推
11/09 16:28, , 17F
11/09 16:28, 17F
推
11/10 12:46, , 18F
11/10 12:46, 18F
推
11/19 23:52, , 19F
11/19 23:52, 19F
※ 編輯: tinlans 來自: 118.160.106.161 (11/22 13:03)
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 2 篇):