Programmer
Programmer

Reputation: 125255

Check if void* to Object with static_cast is successful

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

Answers (2)

mnistic
mnistic

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

Gabriella Giordano
Gabriella Giordano

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

Related Questions