将void *转换为仅在运行时已知的几种类型

时间:2014-12-27 12:44:06

标签: c++ malloc void-pointers generic-programming

我正在将我的C ++程序连接到C ++框架。

框架返回一个void *指针,指向使用malloc()初始化的一组数据:

void* getData() {
    return framework->returnPointer();
}

数据类型仅在运行时(从我的程序中)知道,框架具有以下功能:

size_t ndf_sizeof(ndf_typeid id) {
    switch(id) {
        case NDF_INT64:
            return sizeof(int64_t);
        case NDF_FLOAT:
            return sizeof(float);
        case NDF_DOUBLE:
            return sizeof(double);
    }
    return 0;
}

数据可以采用几种不同的类型,类型存储为ndf_type(即数据类型的整数标识符)。运行期间数据不会更改类型。我可以检索数据的ndf_type,也可以检索数据的大小。

我需要做两件事:

  1. 声明并初始化与运行时数据相同类型的缓冲区
  2. 遍历数据并将值放入我的缓冲区
  3. 我在处理void *指针时遇到困难,并且仅在运行时知道数据类型,这本身可以采用几种不同的类型。我试图使用模板和通用数据结构,但无济于事。

    非常感谢这个问题的解决方案。

2 个答案:

答案 0 :(得分:4)

由于声明在编译期间发生,因此您无法在运行时声明类型。

但是,您可以在编译期间声明所有可能的类型,准备这些类型的指针,并在运行时转换为适当的指针。根据您的要求,我详细说明了这一点。

我假设你有一个指针,说:void * raw_data,你知道类型,ndf_typeid id。

您可以像这样分配所需的指针:

int64_t *p1 = 0;
float   *p2 = 0;
double  *p3 = 0;
switch(id) {
    case NDF_INT64:   p0 = (int64_t  *) raw_data; break;
    case NDF_FLOAT:   p1 = (float    *) raw_data; break;
    case NDF_DOUBLE:  p2 = (double   *) raw_data; break;
}

然而,真正的工作在此之后开始 - 你想做点什么,而且你会有很多"如果"和"案例"语句,以执行您要执行的代码。这就是人们有时使用虚拟方法的原因:

struct Any {
   size_t _size;
   virtual void doit() = 0;
};

template < typename T > struct Typ: Any {
   T _data;
   Typ ( void * data ): _size(sizeof(T)), _data(*(T*)data) {}
   virtual void doit {
      cout << _data << " has size " << _size;
   }
}

Any * any = 0;

switch(id) {
   case NDF_INT64:   any = new Typ<int64_t> (raw_data); break;
   case NDF_FLOAT:   any = new Typ<float  > (raw_data); break;
   case NDF_DOUBLE:  any = new Typ<double > (raw_data); break;
}

any->doit();

这将打印出该值。您可以为每个Typ覆盖doit:

template<> void Typ<float>::doit() {
   cout << "this is a float: " << _data;
}

这可以让你根据类型做不同的工作。

答案 1 :(得分:0)

声明并初始化与运行时数据相同类型的缓冲区

不,你不能这样做,因为你实际上不知道数据的类型。最接近的是声明缓冲区以支持每种类型,然后在运行时决定需要填充哪个缓冲区。