对C识别的指向内部C++类的指针进行类型定义



我有一个类,我想在C和C++之间共享,其中C只能将其作为指针获取。但是,因为它是一个内部类,所以不能向前声明。相反,这是我们当前代码在一个通用头文件中所做的:

#ifdef __cplusplus
class Container {
public:
class Object {
public:
int x;
};
};
typedef Container::Object * PObject;
#else
typedef void* PObject;
#endif

这看起来违反了一个定义规则(ODR(,因为C和C++使用#ifdef看到不同的定义。但因为这是一个指针,我不确定这是否会产生真正的问题。C只使用指针将其传递给C++函数,而不直接使用它做任何事情。例如,公共头文件中的代码:

#ifdef __cplusplus
extern "C" {
#endif
int object_GetX(PObject pObject);
#ifdef __cplusplus
}
#endif /* __cplusplus */

这就是我们在C++文件中实现它的方式:

int object_GetX(PObject pObject) {
return pObject->x;
}

我的问题是:

  1. 这样违反ODR会导致任何真正的问题吗
  2. 如果是,是否有其他方便的方法将类共享给C

首先,类型别名指针通常会带来麻烦
不要这么做。

第二;内部";类是一个被过度使用的概念,所以我的第一反应是考虑它是否真的有必要。

如果有必要,您可以定义一个不透明的空类型,并从中派生一些类型安全性:

在共享标头中:

struct OpaqueObject;
#ifdef __cplusplus
extern "C" {
#endif
int object_GetX(OpaqueObject* pObject);
#ifdef __cplusplus
}
#endif /* __cplusplus */

在C++标头中:


struct OpaqueObject {};
class Container {
public:
class Object : public OpaqueObject {
public:
int x;
};
};

实施:

int object_GetX(OpaqueObject* pObject) {
return static_cast<Container::Object*>(pObject)->x;
}

这样违反ODR会导致任何实际问题吗?

"真正的问题"?大概也许不是。

不存在";混合C/C++ODR规则";。规则是";包含";在一个编程语言中,规范是为一种编程语言编写的。C++有自己的规则,C++是ODR规则。C有自己的规则,而C对ODR一无所知。其他编程语言也有自己的规则。

您并没有违反C++中的ODR——C++到处都是容器的单一定义。

extern "C"中的东西使用C调用约定,我可以假设它也遵循C语言。在这种情况下,你只是违反了规则https://port70.net/~nsz/c/c11/n1570.html#6.5.2.2p9。假设这类似于c中函数的ODR。

如果不是,你违反了语言之间的某些东西,那就是ABI。从C端传递void *指针的值,函数从C++端读取Container::Object *指针的值。这可能是编译器使用的特定ABI所允许的,也可能是未指定的。安全的方法是假设这是不允许的。

是否有其他方便的方法将类共享给C?

C语言也像C++一样提供静态类型检查,但使用void *基本上就是关闭它。不要将C++与C混合。只要为C端取一个不同的唯一名称,你就不会那么困惑了。

此外,pObjectPObject?你的班一定很快!

// object.hpp
#ifdef __cplusplus
class Container {
public:
class Object {
public:
int x;
};
};
typedef Container::Object PObject;
extern "C" {
#endif  
struct C_PObject {
void *pnt;
};
int object_GetX(struct C_PObject obj);
// ...
// object_c.cpp
PObject *object_from_c(struct C_PObject obj) {
return reinterpret_cast<PObject *>(obj.pnt);
}
extern "C"
int object_GetX(struct C_PObject obj) {
return object_from_c(obj)->x;
}

相关内容

  • 没有找到相关文章