我正在开发一个将从C#调用的C ++插件。我尝试移植的API带有数百个函数,其中大多数只是具有相同名称但具有不同数据类型的重载,如int
,float
和char
。
我不是一遍又一遍地在C ++和C#端编写相同的代码但是使用不同的数据类型,而是想使用通用指针对它进行一次函数重载。我的目标是使用static_cast
中的void*
到int
,float
然后char
并使用哪个首先成功。
来自C ++方面的简单测试函数:
void calculate(void* input1, void* input2)
{
float *i1 = static_cast<float*>(input1);
if(i1==NULL)
std::cout<<"Bad"<<std::endl;
else
std::cout<<*i1<<std::endl;
}
int main()
{
int input1 = 5;
int input2 = 10;
calculate(&input1,&input2);
return 0;
}
这应该输出“BAD”,但似乎显示“7.00649e-45”,我认为这是一种未定义的行为。 static_cast
失败了,我不知道如何检查它是否成功。在这种情况下,检查NULL
是否有用。
是否可以检查void*
对象static_cast
是否成功?如果是这样,怎么样?
注意:
这不是this问题的重复。我不想从void*
找出对象的类型。我只想检查转换或static_cast
是否成功。就是这样。
答案 0 :(得分:1)
使用static_cast
来恢复函数参数的类型是不合适的,因为转换将在编译时从void*
到float*
完成。由于存在这种类型的转换链,编译器不会抱怨并且在执行期间,转换本身不会失败,即使它不能保证结果。
同样适用于在调用calculate函数时从int*
到void*
的转换。
对于这种情况,您可以考虑使用模板函数来利用C ++的元编程功能。
这是一个剪辑开头:
template <class T*>
void calculate(T* a, T* b) {
// your implementation here
}
编辑
如果你只需要为一些类型导出模板函数,比如int,float,double等,你可以考虑在你的库的一个cpp文件中为每个类型添加一个模板专门化,其中包括模板功能已声明。
以下是int*
类型的示例。
template __declspec(dllexport) calculate<int*>(int* a, int* b);
答案 1 :(得分:0)
static_cast
不执行类型检查,不能用于可靠地检索类型。此外,传递给您的函数的是void*
指针,此时类型信息将丢失,甚至dynamic_cast
都不会有帮助。因此,即使在纯C ++中,如果没有模板,这也是一个难以解决的问题。 void*
指针实际上是C#System.IntPtr
这一事实使问题复杂化,据我所知,没有足够强大的互操作层来检索原始类型(即使是原始类型)。
像这样的问题是为什么像cog这样的样板代码生成器被发明了。有很多他们在那里,你可能想做一些研究,找到最适合你的需求。 Cog的工作原理是插入嵌入在C ++(或C#或其他)文件中的代码生成脚本,并将其注入到构建过程中。您可能会发现(相对较小的)时间投资(与手动生成样板代码相比)值得。