Reputation: 125255
I am working on a C++ plugin that will be called from C#. The API I am trying to port comes with hundreds of functions and most of them are just overloads with the-same name but with different datatypes like int
, float
and char
.
Instead of writing the-same code but with different datatypes on both C++ and C# side over and over again, I want to use one function overload for it with a generic pointer. My goal is to use static_cast
from void*
to int
, float
and then char
and use which one that is successful first.
A simple test function from the C++ side:
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;
}
This is supposed to output "BAD" but it seems to be showing "7.00649e-45" which I believe is an undefined behavior. The static_cast
is failing and I don't know how check if it is successful or not. Checking if it is NULL
did not help in this case.
Is it possible to check if void*
to Object with static_cast
is successful or not? If so, how?
Note:
This is not a duplicate of this question. I don't want to find out the type of the Object from void*
. I just want check if the conversion or static_cast
is successful or not. That's it.
Upvotes: 5
Views: 4909
Reputation: 11020
static_cast
performs no type checking and cannot be used to reliably retrieve the type. Furthermore, what is passed into your function is a void*
pointer, at which point type information is lost and not even dynamic_cast
would help. So this would be a hard problem to solve without templates even in pure C++. The fact that the void*
pointer is actually a C# System.IntPtr
compounds the problem and to the best of my knowledge there is no interop layer powerful enough to retrieve the original type (even if primitive).
Problems like this one is why boilerplate code generators like cog were invented. There are a bunch of them out there and you may want to do some research to find which one best fits your needs. Cog works by inserting code generation scripts embedded right in C++ (or C#, or whatever) files and can be injected into your build process. You may find it worth the (relatively small) time investment (compared to generating the boilerplate code manually).
Upvotes: 0
Reputation: 1238
The use of static_cast
to recover the type of the argument of your function is not appropriate because the casting will be done at compile time from void*
to float*
. Since a conversion chain for this types exists, the compiler will not complain and during execution, the casting itself will not fail, even if there is no guarantee on the result of it.
The same applies to the casting from int*
to void*
when invoking the calculate function.
Maybe for this case you could consider the use of a template function to exploit the metaprogramming feature of C++.
Here is a snipped to start with:
template <class T*>
void calculate(T* a, T* b) {
// your implementation here
}
EDIT
If you need to export the template function only for a few types, like int, float, double etc you may consider adding this a template specialization for each type in one of the cpp files of your library that includes the header where the template funcion is declared.
Here is an example for the int*
type.
template __declspec(dllexport) calculate<int*>(int* a, int* b);
Upvotes: 1