我正在将我的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,也可以检索数据的大小。
我需要能够做两件事:
- 在运行时声明并初始化与数据类型相同的缓冲区
- 循环访问数据并将值放入我的缓冲区
在处理 void* 指针并且仅在运行时知道数据类型时,我的困难就会发生,这本身可以采用几种不同的类型。我尝试使用模板和通用数据结构,但无济于事。
非常感谢此问题的解决方案。
由于声明发生在编译时,因此不能在运行时声明类型。
但是,您可以在编译时声明所有可能的类型,准备这些类型的指针,并在运行时强制转换为适当的指针。应你的要求,我详细说明。
我假设你有一个指针,比如: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;
}
然而,真正的工作在那之后开始 - 你想做一些事情,你会有很多"if"和"case"语句来执行你想要执行的代码。这就是为什么有时人们使用虚拟方法的原因:
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;
}
这使您可以根据类型执行不同的工作。
在运行时声明并初始化与数据类型相同的缓冲区
不,您不能这样做,因为您实际上不知道数据类型。您可以做的最接近的事情是声明支持每种类型的缓冲区,然后在运行时决定需要填充哪个缓冲区。