简体   繁体   English

从C ++到C的转换

[英]conversion from C++ to C

Hi I am interested by converting some code from C++ to C (mostly because i need to use the library with/from other C program and other language) . 嗨,我很感兴趣将某些代码从C ++转换为C(主要是因为我需要将库与其他C程序和其他语言一起使用)。 C is a better gateway for that I am interested to replicate few C++ concept like inheritance for inst . C是一个更好的网关,因为我有兴趣复制一些C ++概念,例如inst的继承。

Does anyone know good references or has already work on some similar issues. 有谁知道良好的参考文献或已经处理过一些类似的问题。 For inst how to deal with inheritance , adding new members variable/ methods to child class , ... 有关如何处理继承的信息,请向子类添加新的成员变量/方法,...

Thx for your help 谢谢你的帮助

if you need to call the lib from C, i would design a clean C API that internally calls the C++ functions. 如果您需要从C调用lib,我会设计一个干净的C API,在内部调用C ++函数。 The linkage is different between C and C++ , so, you must specify: C和C ++之间的链接不同,因此,您必须指定:

#ifdef __cplusplus
extern "C" { 
#endif

void my_c_function (void );

#ifdef __cplusplus
}
#endif

About desing, you must hide classes , templates, etc. I suggest you to read some C libraries, like libpng or OpenGL 1.0, to get an idea of a pure C interface. 关于设计,您必须隐藏类,模板等。我建议您阅读一些C库,例如libpng或OpenGL 1.0,以获得纯C接口的想法。

In C , you must construct and delete "objects" by yourself. 在C中,您必须自己构造和删除“对象”。 You can use some kind of object oriented programming if you pass the "this" pointer for your "objects" in each call. 如果在每次调用中为您的“对象”传递“ this”指针,则可以使用某种面向对象的编程。

But unfortunately, you will have something like "void pointers". 但是不幸的是,您会遇到类似“空指针”的问题。 You can use handles (like win32) if you dont want to expose your internal memory. 如果您不想公开内部内存,则可以使用句柄(例如win32)。

Here's a quick example of how you might go about wrapping a C++ class or API in a C-callable API that does little more than forward the C calls to the C++ object. 这是一个简单的示例,说明了如何将C ++类或API封装在可调用C的API中,该功能仅将C调用转发给C ++对象即可。

Suppose you have a C++ library with the following interface: 假设您具有一个带有以下接口的C ++库:

class stopwatch
{
public:
    void start();
    void stop();
    void reset();

    unsigned int get_elapsed();

private:
    // whatever...
};

Your C API might have a interface that's described by the following header: 您的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

Note that the above header is designed to be included in either C or C++ modules, and the appropriate parts are marked as being extern "C" when compiled in a C++ module. 请注意,上述标头旨在包含在C或C ++模块中,并且在C ++模块中编译时,相应的部分被标记为extern "C"

Now the implementation of that C API is done in a .cpp module so it can access the C++ library, but it presents the C-callable interface. 现在,该C API的实现是在.cpp模块中完成的,因此它可以访问C ++库,但是它提供了C可调用的接口。

#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();
}

Note that in the stopwatch_create() function we call a variant of operator new that won't throw an exception on failure, since that will often make little sense (unless you expect that the exception should terminate the program or that there will be an appropriate handler further along the stack). 请注意,在stopwatch_create()函数中,我们调用了一个new运算符的变体,该变体不会在失败时引发异常,因为这通常没有多大意义(除非您期望该异常会终止程序或会有一个适当的终止符)。处理程序)。 This kind if thing might make your C API functions a little more complex if they need to handle possible exceptions and 'convert' them to an error handling mechanism that's appropriate for C. 如果需要处理可能的异常并将它们“转换”为适用于C的错误处理机制,这种情况可能会使您的C API函数复杂一些。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM