您好 我感兴趣的是将一些代码从C ++转换为C(主要是因为我需要使用带有/来自其他C程序和其他语言的库)。 C是一个更好的网关 我有兴趣复制一些C ++概念,比如inst。继承。
有没有人知道好的推荐或已经处理过一些类似的问题。对于inst如何处理继承,将新成员变量/方法添加到子类,...
感谢您的帮助
答案 0 :(得分:7)
如果你需要从C调用lib,我会设计一个内部调用C ++函数的干净的C API。 C和C ++之间的链接是不同的,因此,您必须指定:
#ifdef __cplusplus
extern "C" {
#endif
void my_c_function (void );
#ifdef __cplusplus
}
#endif
关于设计,你必须隐藏类,模板等。我建议你阅读一些C库,比如libpng或OpenGL 1.0,以了解纯C接口。
在C中,您必须自己构造和删除“对象”。如果在每次调用中为“对象”传递“this”指针,则可以使用某种面向对象的编程。
但不幸的是,你会有类似“无效指针”的东西。如果您不想暴露内部存储器,可以使用句柄(如win32)。
答案 1 :(得分:4)
以下是一个快速示例,说明如何在C调用API中包装C ++类或API,只需将C调用转发给C ++对象。
假设您有一个带有以下接口的C ++库:
class stopwatch
{
public:
void start();
void stop();
void reset();
unsigned int get_elapsed();
private:
// whatever...
};
您的C API可能具有以下标题所描述的界面:
#ifndef STOPWATCH_API_H
#define STOPWATCH_API_H
#if __cplusplus
extern "C" {
#endif
struct stopwatch_handle;
stopwatch_handle* stopwatch_create(void);
void stopwatch_delete( struct stopwatch_handle*);
void stopwatch_start(struct stopwatch_handle*);
void stopwatch_stop(struct stopwatch_handle*);
void stopwatch_reset(struct stopwatch_handle*);
void stopwatch_get_elapsed(struct stopwatch_handle*);
#if __cplusplus
}
#endif
#endif
请注意,上述标题旨在包含在C或C ++模块中,并且在C ++模块中编译时,相应的部分标记为extern "C"
。
现在,该C API的实现是在.cpp模块中完成的,因此它可以访问C ++库,但它提供了C-callable接口。
#include <new> // for nothrow new
#include "stopwatch.h" // the C++ library API
#include "stopwatch_api.h" // the C callable interface that's being
// implemented here
struct stopwatch_handle {
stopwatch impl; // the C code never needs to know about this
// internal part of the struct, since all that
// the C client code will deal with is an
// opaque pointer
};
extern "C"
stopwatch_handle* stopwatch_create(void)
{
// use nothrow new since it doesn't make sense to
// have an exception bubble up to C code
return new(std::nothrow) stopwatch_handle;
}
extern "C"
void stopwatch_delete( struct stopwatch_handle* p)
{
delete p;
}
extern "C"
void stopwatch_start(struct stopwatch_handle* p)
{
p->impl.start();
}
extern "C"
void stopwatch_stop(struct stopwatch_handle* p);
{
p->impl.stop();
}
extern "C"
void stopwatch_reset(struct stopwatch_handle* p)
{
p->impl.reset();
}
extern "C"
unsigned int stopwatch_get_elapsed(struct stopwatch_handle* p)
{
return p->impl.get_elapsed();
}
请注意,在stopwatch_create()
函数中,我们调用运算符new
的变体,它不会在失败时抛出异常,因为这通常没有意义(除非您预期异常应该终止程序或在堆栈中将有一个适当的处理程序)。如果他们需要处理可能的异常并将它们“转换”为适合C的错误处理机制,那么这种情况可能会使您的C API函数变得更复杂。