Given a base class B
, such as:
class B
{
public:
virtual ~B() = default;
public:
virtual int f() const = 0;
};
and a number of derived classes Ai: public B
(i=1,..,N), implementing f()
, I receive a void*
definitely holding one of the derived Ai
classes from the external program - to execute the f()
method.
It's possible to create an entry point for each possible derived type, and it will work fine:
// for each derived class Ai
void executeF(void* aPtr, int* result)
{
auto aObjPtr = static_cast<Ai*>(aPtr);
*result = aObjPtr->f();
}
However, it should be possible to achieve the same result with single function only, such as:
void executeF(void* aPtr, int* result)
{
auto bObjPtr = static_cast<B*>(aPtr); // works
*result = bObjPtr->f(); // Access violation
}
The case succeeds in the above, but the execution of f()
fails with "Access violation" in MSVC 2013.
Is there something wrong with the above function? And if so, is there a way to achieve the task with a single function?
I've read some materials, which claim that one has to cast void*
only to the particular class, which it holds (also suggested in the comment below). However, this code compiles and executes fine: http://ideone.com/e0Lr6v
Some more context about how everything is being called:
I can't provide the entire code here because it's too long but in summary.. The function executeF
, constructors for objects Ai
and everything in the library that defines and operates on objects A
, B
are provided as exported functions that operate on void*
types only. Just FYI, this library is being compiled and build with MSVC 2013.
Another side (the wrapper for R language) is compiled and built with g++ - it loads the above library dynamically, exports needed function and calls it. The only thing that is available on this side is the void*
holding objects Ai
- it just sends requests to create objects, calls their methods, frees them.
For example (schematically), create an object of type A1:
// "objects" library
void createA1(void** aObj)
{
*a1Obj = new A1();
}
// caller library
auto const createA1func = (int(__CC *)(void**)) GetProcAddress(getDLL(), "CreateA1");
void* a1Obj = NULL;
createAFunc(a1Obj);
// ... return the a1Obj to the external environemnt to keep it around
Then, having a1Obj
around, do some job with it:
// caller library
auto const executeFfunc = (int(__CC *)(void*, int*)) GetProcAddress(getDLL(), "executeF");
int res(0);
executeFfunc(a1Obj, &res);
So if I write a separate function for each type Ai
on both sides, everything works OK. But it'd be significantly less boilerplate code if I can use the base class here somehow.