【问题标题】:Redefining a handle ptr of void* to handle ptr to struct* (C/C++ mixcode) for access重新定义 void* 的句柄 ptr 以将 ptr 处理为 struct* (C/C++ mixcode) 以进行访问
【发布时间】:2023-03-03 03:34:01
【问题描述】:

我有 C/C++ 混合代码并希望传递一个包含对类的引用的结构。因此,我不能在 C++ 组件的头文件中声明这个结构(因为类是在 C++ 组件的源文件中定义的),而只能在源文件中声明。然而,C 中的主脚本必须以某种方式引用该结构,因此我将其 typedef 为 void*。但是正因为如此,我不能将句柄类型取消引用回结构。无法在源文件中重新定义句柄指针。我该如何解决这个问题?

header_with_obj.hpp

class A {
    int a;
};

header.hpp

typedef void* config_handle_t;

source.cpp

#include "header.hpp"
#include "header_with_obj.hpp"

typedef struct {
    A* ptr;
    int some_other;
} config_t;

// typedef config_t* config_handle_t <-- error: conflicting declaration 'typedef struct config_t* config_handle_t '

int foo(void* arg)
{
    config_handle_t handle = (config_handle_t) arg;
    handle->A.a = 4; //  <-- error: 'config_handle_t' {aka 'void*'} is not a pointer-to-object type
}

ma​​in.c

#include "header.hpp"

int main()
{
    // we get that void* from somewhere and pass it in
    foo(arg);
}

【问题讨论】:

  • 你可以在没有任何转换的情况下做到这一点:把它放在header.hpp:typedef struct config_t* config_handle_t; 指向不完整类型的指针在 C 和 C++ 中都是有效的。并且您保留了类型安全性(有人不会意外传递int*)。
  • 怎么样?我得到error: unknown type name 'config_t' typedef config_t* config_handle_t; 这是有道理的,因为 struct config_t 的声明在源文件中。
  • @glades 你写的是 config_t 而不是 struct config_t。此外,您还必须将结构声明为 struct config_t {...}; 而不是 typedef struct {...} config_t;,因为在第二个结构中,该结构在技术上没有名称。
  • @RaymondChen 这是正确答案:您应该将其设为答案而不是评论。
  • @user253751:谢谢你现在的工作!多么微妙的区别,但我一直想知道 typedef 和 struct 实际上的区别是什么。如果我没记错的话,我想我现在必须将一些 malloc(sizeof(config_t)) 更改为 malloc (sizeof(struct config_t))?

标签: c++ c class typedef void-pointers


【解决方案1】:

通常的方法是使用未定义的结构。最基本的形式:

void foo(struct the_config_struct *arg);
// OK even though 'struct the_config_struct' wasn't defined!
// surprisingly this is also allowed in C++

你也可以做一个typedef:

typedef struct the_config_struct *config_handle_t;
void foo(config_handle_t arg);

如果您愿意,您甚至可以将 typedef 称为与结构相同的东西。只是为了避免混淆人们,我不会这样做,除非它是结构的 typedef (不是指针)。

typedef struct the_config_struct the_config_struct;
void foo(the_config_struct *arg);

在您想要访问其成员之前,您实际上并没有定义该结构:

// if we uncomment this definition then it's OK
// struct my_struct {
//     char *message;
// };

void foo(struct my_struct *arg) {
    puts(arg->message); // error: struct my_struct is undefined
}

最后(因为这让你很困惑)你应该知道 typedef 名称和结构名称在 C 中是完全分开的。

struct foo {}; // defines "struct foo" but "foo" is completely unrelated
typedef int bar; // defines "bar" but "struct bar" is completely unrelated

foo *get_foo(); // error: "foo" is unknown
struct foo *get_foo(); // OK

typedef struct bar foo;
foo *get_bar(); // OK: returns pointer to struct bar (not struct foo!)
struct foo *get_foo(); // this one returns pointer to struct foo

struct baz {};
typedef struct baz baz;
// now "baz" is an alternative name for "struct baz" - they are interchangeable

typedef struct baz {} baz; // short version

结构不必有名字:

// foo is a variable, and it's a struct variable, but the struct has no name.
// so we have no way to use the struct for anything else.
struct {
    int i;
} foo;

// The struct is still there even though it doesn't have a name!
// In C++ you can write decltype(bar) to say "the same type as variable bar".
// Even though we don't know the person's name we can still yell out "Hey you in the red shirt!"
decltype(foo) foo2; // a variable foo2. The type is decltype(foo) i.e. the struct from before

// GCC lets you do it in C using "typeof".
// This is not standard. It's a special feature in GCC.
typeof(foo) foo2;

// This struct also has no name either. But the typedef means we have
// an "unofficial" way to name it, just like decltype(foo) before.
// This is valid in C as well as C++.
typedef struct {
    char message[50];
} bar;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-28
    • 2010-12-22
    • 2019-05-21
    • 1970-01-01
    • 2019-10-23
    • 1970-01-01
    相关资源
    最近更新 更多