我有c ++库.so。我的同事正在研究c程序,它将从他的c程序中调用c ++库。我告诉他创建Wrapper.h和Wrapper.cpp并使用指针在他的c程序中传递c ++对象。但是,我发现他试图通过将Wrapper.cpp和header添加到我们的库.so中来直接修改我们的c ++库源代码。例如:
class A{ SetValueA(int); }
class B{ SetValueB(int); }
在他的Wrapper.cpp中,他写的是这样的:
A a;
B b;
extern "C" SetValueA(int) {a.SetValueA(int); }
extern "C" SetValueB(int) {b.SetValueB(int); }
然后他重新编译了我们的c ++库,并在他的c程序中包含了Wrapper.h。
我告诉他的是这样做: 在我的Wrapper.cpp
中extern "C" {
A* newClassA() {
return new A();
}
void SetValueA(A* v, int i) {
v->SetA(i);
}
B* newClassB() {
return new B();
}
void SetValueB(B* v, int i) {
v->SetB(i);
}
void deleteClassA(A* v) {
delete v;
}
void deleteClassB(B* v) {
delete v;
} }
然后我编译了我的Wrapper.cpp并与我们的c ++库链接。在他的c程序中,他只需要包含Wrapper.h并编译他的c代码,然后使用c ++编译器编译Wrapper.o和main.o(来自main.c)。
他的解决方案看起来也很有效,他抱怨说我告诉他的方式更多。但我不希望他改变我们的c ++库因为没有人会使用来自c ++库的Wrapper类。你能告诉我哪一个更好,为什么?
是的,我也不喜欢他在包装器中使用全局变量的方式。
答案 0 :(得分:3)
我不明白为什么需要更改任何库文件以使用全局变量:必要的更改应限于Wrapper.cpp
,这显然是包装器的一部分。
那就是说,我不相信使用任何[可变]全局对象。它们往往以许多不同的方式成为问题。也就是说,我同意创建包装器的正确方法是有效地处理必要的生命周期管理。我确实意识到用C语言正确排序生命周期管理比用C ++更难。解决这个问题的方法是使用C ++,而不是创建不必要的依赖项(我知道这个参数通常不会与C程序员一起使用)。
答案 1 :(得分:0)
你的同事写的包装器当然是不可检测的,因为使用了全局变量,这会在你的库中引入很多问题。
但是,我相信,一个编写良好的库应该自己导出一个C接口,即使它在内部使用C ++也是如此。原因很简单,C接口几乎可以导入到每种语言中,而C ++接口要求用户代码为C ++。此外,强制使用这种包装器进入用户代码可能会导致不同的wrapper.cpp版本激增,所有这些版本都是不完整的,并且以不同的方式过时。
因此,我会将您的wrapper.cpp行中的代码包含到您的库中。我肯定会把它移到它包装的代码附近,而不是将它们全部捆绑在一个大的胖包装器中。这样就可以更容易地检查所有公共方法是否都已正确包装。