简体   繁体   English

C struct 指向 C++ 类的指针

[英]C struct pointer to C++ class

I am writting a C shared library that will be loaded into a C++ program.我正在编写一个 C 共享库,它将被加载到 C++ 程序中。 There is an object in this program that I need access to, so I am gonna be using a struct pointer.这个程序中有一个我需要访问的对象,所以我将使用结构指针。 But I'm not really sure how can I make a C struct pointer to a C++ class, as it also constains functions (constructor, destructor, etc).但我不太确定如何创建指向 C++ 类的 C 结构指针,因为它也包含函数(构造函数、析构函数等)。 I think it is possible though, as a struct is just holds data, meaning that I can arrange it in a way it matches the C++ class in the memory.我认为这是可能的,因为结构只是保存数据,这意味着我可以按照与内存中的 C++ 类匹配的方式排列它。 Example:例子:

//C++ class
class test
{
    public:
    int   number;
    char* string;

    public:
    test();
    ~test();
    void function(int new_number);
    void function(char* new_string);
} obj;
//C struct pointer

struct test_t
{
    //???
};

//...
struct test_t* p_obj = (struct test_t*)addr_of_obj;

Any ideas?有任何想法吗?

EDIT: I cannot edit the source code of this program that I'm loading the library into.编辑:我无法编辑我正在加载库的这个程序的源代码。 I'm forcing it to load this library that will access and modify memory for me.我强迫它加载这个库,它将为我访问和修改内存。

After some testing, I think the answer to this question is: depends on the compiler and on the class.经过一些测试,我认为这个问题的答案是:取决于编译器和类。 The examples I will give below were compiled with GCC and G++ on Linux (seems to work with clang and clang++ too).我将在下面给出的示例是在 Linux 上使用 GCC 和 G++ 编译的(似乎也适用于 clang 和 clang++)。

Example 1 - A class with some variables, a constructor, a destructor, and an overloaded function - nothing too special about it.示例 1 - 一个包含一些变量、构造函数、析构函数和重载函数的类 - 没什么特别的。

//C++ class
class test
{
    private:
    int number;
    char* string;

    public:
    test() { this->number = 0; this->string = (char*)""; this->boolean = false; }
    ~test() {  }
    void function(int num) { this->number = num; }
    void function(char* str) { this->string = str; }
    int    get_number() { return this->number; }
    char*  get_string() { return this->string; }

    bool boolean;
};
//C structure
//To create a struct pointer for this class, I just had to ignore the functions. 

struct test_t
{
    int number;
    char* string;
    bool boolean;
};

Example 2 - a class that contains virtual functions.示例 2 - 包含虚函数的类。 In this case, we'd have to add an extra pointer parameter on the beginning of our structure.在这种情况下,我们必须在结构的开头添加一个额外的指针参数。 That would be aligned with the virtual function table of that class, which is no longer hidden because of the virtual function.这将与该类的虚函数表对齐,由于虚函数不再隐藏。

//C++ class
class test
{
    private:
    int number;
    char* string;

    public:
    test() { this->number = 0; this->string = (char*)""; this->boolean = false; }
    ~test() {  }
    virtual void v_function()  { printf("virtual function\n"); }
    virtual void v_function2() { printf("another virtual function\n"); }
    void function(int num) { this->number = num; }
    void function(char* str) { this->string = str; }
    int    get_number() { return this->number; }
    char*  get_string() { return this->string; }

    bool boolean;
};
//C structure
//It is the same as before, but with the VFT pointer
struct test_t
{
    void** vptr; //A pointer to function addresses (void**)
    int number;
    char* string;
    bool boolean;
};

In conclusion, the only way to be 100% sure your C structure pointer aligns with the C++ class is looking on the memory and aligning it manually.总之,100% 确保您的 C 结构指针与 C++ 类对齐的唯一方法是查看内存并手动对齐它。 And you can aways skip some variables by putting pads in your structure:你可以通过在你的结构中放置 pads 来跳过一些变量:

//C++ class
class test
{
    private:
    int number;
    std::vector<std::string> vector;
    char* string;

    public:
    test() { this->number = 0; this->string = (char*)""; this->boolean = false; }
    ~test() {  }
    virtual void v_function()  { printf("virtual function\n"); }
    virtual void v_function2() { printf("another virtual function\n"); }
    void function(int num) { this->number = num; }
    void function(char* str) { this->string = str; }
    int    get_number() { return this->number; }
    char*  get_string() { return this->string; }

    bool boolean;
};
//C structure
struct test_t
{
    void** vptr;
    int number;
    char vector[24]; //std::vector<std::string> pad (24 bytes long)
    char* string;
    bool boolean;
};

The way to do that and keep code easy to support is to use C definitions from C++ code.做到这一点并使代码易于支持的方法是使用 C++ 代码中的 C 定义。 Perhaps using private implementation to lessen compatibility issues.也许使用私有实现来减少兼容性问题。

//C struct - non-static data

struct test_t
{
    int   number;
    char* string;
};

C++ wrapper for test_t . test_t C++ 包装器。

// C++ interface

struct  test_t;
struct test
{
    test_t *priv; //private implementation
public:
    // methods.
};

How class es and struct s are laid out in memory are not defined by the C and C++ standards the are however laid out in platform specific Application Binary Interface (ABI) documents. C 和 C++ 标准没有定义class es 和struct s 在内存中的布局方式,但在特定于平台的应用程序二进制接口 (ABI) 文档中进行了布局。 To ensure safety you must ensure the layouts match.为确保安全,您必须确保布局匹配。 You will certainly run into issues if any functions are virtual.如果任何功能是虚拟的,您肯定会遇到问题。

A safer option will be to either embed the extern "C" struct in your C++ class or hide the class from the C code and just allow access via extern "C" accessor functions.更安全的选择是将extern "C"结构嵌入到 C++ 类中,或者从 C 代码中隐藏该类,只允许通过extern "C"访问器函数进行访问。

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

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