C ++ 11有sleep_for
。但是C标准没有等价物。
我想我可以编写一个包装器来从C调用这样的C ++函数。
还有像Boost Filesystem和Asio这样的有用库。这些更复杂,但我也可以编写包装器。
它可以重新发明轮子吗?这可能是一个坏主意吗?
答案 0 :(得分:2)
这个问题是,如果你想编写调用Boost函数的C包装器,如果抛出异常你会怎么做?你基本上必须在它到达C之前在调用者中吞下它,但是将它正确地报告给C有点尴尬然后有很多类型的例外。
通常人们在特别想要额外的可移植性时使用C而不是C ++,或者由于某种原因无法提供所有C ++依赖。如果你想编写一个使用boost :: filesystem的C程序,为什么不把它编译成C ++呢?你可以用更少的异常处理锅炉板代码来编写,而且可以减少错误。
答案 1 :(得分:2)
zeroMQ这样做。该库是用C ++编写的,但库API是C接口。原则上,您将类隐藏在对象大小的内存块中并传递void*
。对于一些简单的功能,例如sleep_for
,你可以创建一个包装函数。在标题中,声明
extern "C" {void sleep_for(int duration);}
在您的cpp文件中,请按std::this_thread::sleep_for
。
sleep_for(int duration) {std::this_thread::sleep_for( std::chrono::milliseconds(duration);}
对于类,您需要C函数来创建新对象,破坏它,当然还需要调用成员函数。对于A类,这可能如下所示:
C头文件“A_C_API.h”:
extern "C" {
enum {SIZE_OF_A = 4};
typedef char[SIZE_OF_A] a_class;
a_class initA(void* a, int x);
void destructA(void* a);
int callGet(void *a);
}
C++ source file:
class A {
public:
A(int i): x{i} {}
int get() const {return x;}
private:
int x;
};
static_assert( SIZE_OF_A == sizeof(A), "size mismatch!");
void initA(void* a, int x) {
new (a) A(x);
}
void destructA(void* a) {
static_cast<A*>(a)->~A();
}
int callGet(void *a) {
return static_cast<A*>(a)->get();
}
在您的C应用程序中,您可以
#include "A_C_API.h"
int main(int argc, char* argv[]) {
a_class obj;
initA(&obj);
printf("%d", callGet(&obj) );
destructA( &obj );
return 0;
}
您必须捕获异常并将其转换为某些C错误处理。您还必须处理某些平台上的对齐问题,尤其是SPARK平台。为简单起见,我省略了这一点,但你可以看看zeromq标头如何做到这一点。