简体   繁体   English

如何使用模板化的C ++结构定义C-forward声明的不透明结构

[英]How to define C-forward declared opaque struct with a templated C++ struct

Given the C declaration of opaque type (cheader.h) 给定不透明类型的C声明(cheader.h)

typedef struct internal_data * Opaque;

I want to declare "internal_data" as an instance of the template (cppheader.h) 我想将“ internal_data”声明为模板的实例(cppheader.h)

namespace Lib {
template<typename T>
struct Internal {
    T data;
};

template<typename T>
Internal<T>* Initialise(T data) {
    Internal<T>* t = new Internal<T>();
    t->data = data;
    return t;
}
}

So that the following function compiles: 这样可以编译以下函数:

#include "cppheader.h"
#include "cheader.h"

int main(int argc, char** argv)
{
    Opaque o = Lib::Initialise(argc);
    return 0;
}

I can't modify the C header. 我无法修改C标头。 The C++ header isn't exposed, so I can modify that one at will. C ++标头未公开,因此我可以随意修改它。 The instantiated template needs to be POD. 实例化的模板需要是POD。 There are multiple opaque types on the C header that I omitted for simplicity. 为了简单起见,我省略了C头上的多个不透明类型。 They are all supposed to dereference to instantiations of the C++ template. 它们都应该取消引用C ++模板的实例。

I've tried 我试过了

typedef Lib::Internal<int> internal_data;

and

struct internal_data : Lib::Internal<int> {};

but neither compiles. 但都没有编译。

From what I can make out, this looks something typical of the C to C++ and vice-versa API mapping. 据我所知,这看起来是C到C ++的典型代表,反之亦然。

Given that you can't change the C header file, the definition of Opaque is constrained and essentially can't be typed to any C++ constructs contained in C++ header file. 鉴于您无法更改C头文件,因此Opaque的定义受到约束,并且本质上不能键入C ++头文件中包含的任何C ++构造。

It's a little ugly in a purist sense, but you can use reinterpret_cast for this. 从纯粹的角度来看,这有点丑陋,但是您可以为此使用reinterpret_cast

In the cppheader; 在cppheader中;

struct internal_data {};

template<typename T>
struct Internal {
    T data;
};

template <typename T>
Opaque map_internal(Internal<T>* p)
{
  return reinterpret_cast<Opaque>(p);
}

template <typename T>
Internal<T>* remap_internal(Opaque p)
{
  return reinterpret_cast<Internal<T>*>(p);
}

And then the internal Initialise changes to; 然后内部Initialise更改为;

template<typename T>
Opaque Initialise(T data) {
    Internal<T>* t = new Internal<T>();
    t->data = data;
    return map_internal(t);
}

You don't mention anything around resource management, but the reverse of map_internal can be used to cast the Opaque back to Internal<T> for the corresponding delete when required. 关于资源管理,您没有提及任何内容,但是在需要时,可以使用map_internal的相反操作将Opaque投射回Internal<T>进行相应的delete

Note: type safety is a concern here (wrt the reinterpret_cast ), but in this case the trade-off is type safety vs. interoperability. 注意:这里需要考虑类型安全性(将reinterpret_cast ),但是在这种情况下,需要权衡的是类型安全性与互操作性。 Because of strict aliasing, you should not attempt to access any data that may (in future) be in internal_data , it is there just to convert from and back to Internal<T> . 由于严格别名,你应该试图访问可能(在未来)是任何数据internal_data ,它的存在只是为了从转换和回Internal<T>

Worth noting here is cppreference , conversion 5, related to the C++ specification 5.2.10. 此处值得注意的是cppreference ,转换5,与C ++规范5.2.10相关。

Any pointer to object of type T1 can be converted to pointer to object of another type cv T2. 指向类型T1的对象的任何指针都可以转换为指向另一类型cv T2的对象的指针。 This is exactly equivalent to 这完全等同于

static_cast<cv T2*>(static_cast<cv void*>(expression)) . static_cast<cv T2*>(static_cast<cv void*>(expression))

Live sample 现场样品

If you don't want to reinterpret_cast<> , you can inherit from a dummy internal_data , ie 如果您不想reinterpret_cast<> ,则可以从虚拟internal_data继承,即

struct internal_data {};
template<typename T>
struct Internal: internal_data {
    T data;
};

When you need to access the data just down-cast from the pointer to your template type. 当您需要访问数据时,只需将指针向下转换到模板类型即可。

Maybe union would help? 工会会有所帮助吗?

template<typename T>
union InternalExtend
{
    Internal<T>* internal;
    Opaque opaque;
};

template<typename T>
Opaque Initialise(T data) {
    InternalExtend<T> ret;
    ret.internal = new Internal<T>();
    ret.internal->data = data;
    return ret.opaque;
}

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

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