Converting C to CPP with Function Pointers - c++

In my C code, I have the following lines:
void* (*functionSteps[numSteps])();
functionSteps[0] = (void*) filterEvenFoos;
functionSteps[1] = (void*) timesFooByTwo,
functionSteps[2] = (void*) mapFooToBar;
Which works fine. I have an array of functions that return a void* type and take any number of inputs.
I tried to do the same in C++ and I'm getting the error
assigning to 'void *(*)()' from incompatible type 'void *'
Is this not possible in CPP?

Is this not possible in CPP?
functionSteps[0] = (void*) filterEvenFoos;
No, it is not.
It is not really valid C either.
Regarding Function To Pointer Conversion
From https://en.cppreference.com/w/c/language/conversion#Function_to_pointer_conversion:
Any function designator expression, when used in any context other than
as the operand of the address-of operator
as the operand of sizeof
undergoes a conversion to the non-lvalue pointer to the function designated by the expression.
It does not say anything about converting a void* to a function pointer.
Regarding Conversions From void*
You can convert a void* to an object pointer.
From https://en.cppreference.com/w/c/language/conversion#Pointer_conversions:
A pointer to void can be implicitly converted to and from any pointer to object type with the following semantics:
If a pointer to object is converted to a pointer to void and back, its value compares equal to the original pointer.
No other guarantees are offered
Please note even in that section, there is no mention of converting a void* to a function pointer.
It's not clear to me why your computer does not report it as an error.
You can use
functionSteps[0] = filterEvenFoos;
if filterEvenFoos is of the right type of function. If the declaration of filterEvenFoos does not exactly match the expected type, i.e. a function that takes no arguments and returns a void*, then you can't use that either.

Is this not possible in CPP?
Strictly speaking, no, due to type safety and other rules governing function prototypes. However, depending on your needs, that C code can be ported to C++.
Firstly, it should be noted that the function signature of void* fn(); in C is not the same in C++. In C++ to get the same function signature, you need to introduce variadic arguments like so: void* fn(...);, however, it should be noted that you cannot access the variadic arguments portably for a function signature like this.
In C++, void* fn(); is the same as void* fn(void); in C. To this, if your functions had variable inputs in C, you would need to do a little extra work in C++ using the variadic argument list.
For example, if your code were something similar to the following C code:
#include <stdio.h>
#define NUM_STEPS 3
static void* filterEvenFoos(void)
{
printf("42\n");
return NULL;
}
static void* timesFooByTwo(int val)
{
printf("%d\n", (val * 2));
return NULL;
}
static void* mapFooToBar(double obj1, size_t obj2)
{
printf("foo(%f)->bar(%zu)\n", obj1, obj2);
return NULL;
}
int main(void)
{
void* (*functionSteps[NUM_STEPS])();
functionSteps[0] = (void*)filterEvenFoos;
functionSteps[1] = (void*)timesFooByTwo;
functionSteps[2] = (void*)mapFooToBar;
functionSteps[0]();
functionSteps[1](42);
functionSteps[2](3.14, &main);
return 0;
}
You could port it to C++ in many ways, but you could use the va_arg functionality to get variable inputs like so:
#include <iostream>
#include <cstdarg>
#include <vector>
static void* filterEvenFoos(int na, ...)
{
std::cout << 42 << std::endl;
return NULL;
}
static void* timesFooByTwo(int na, ...)
{
va_list vl;
va_start(vl, na);
std::cout << ((va_arg(vl, int)) * 2) << std::endl;
va_end(vl);
return NULL;
}
static void* mapFooToBar(int na, ...)
{
va_list vl;
va_start(vl, na);
double obj1 = va_arg(vl, double);
size_t obj2 = va_arg(vl, size_t);
std::cout << "foo(" << obj1 << ")->bar(" << obj2 << ")" << std::endl;
va_end(vl);
return NULL;
}
int main(int argc, char* argv[])
{
std::vector<void* (*)(int, ...)> functionSteps;
functionSteps.push_back(&filterEvenFoos);
functionSteps.push_back(&timesFooByTwo);
functionSteps.push_back(&mapFooToBar);
functionSteps[0](0);
functionSteps[1](0, 42);
functionSteps[2](0, 3.14, &main);
return 0;
}
You might note that the function signature changes slightly to allow a portable way to access the variadic arguments in each function.
If you're using C++11, you could also make use of the std::function inside the vector, but you still need to have matching function signatures.
You could also make use of classes and inheritance, or template specializations, but those could be extreme over-kill in your scenario.
In the end, it's not a direct port from the C code to C++, but it is doable.
Hope that can help.

It's possible, but the syntax is a bit dicey to get right. It's easier if you use a typedef for your callback-function-type, like this:
#include <stdio.h>
void* filterEvenFoos() {return NULL;}
void* timesFooByTwo() {return NULL;}
void* mapFooToBar() {return NULL;}
typedef void* (*VoidFunction)();
int main(int, char **)
{
const int numSteps = 3;
VoidFunction functionSteps[numSteps];
functionSteps[0] = filterEvenFoos;
functionSteps[1] = timesFooByTwo;
functionSteps[2] = mapFooToBar;
}

Related

Pointer to Pointer Memory-address [duplicate]

Under what circumstances might you want to use multiple indirection (that is, a chain of pointers as in Foo **) in C++?
Most common usage as #aku pointed out is to allow a change to a pointer parameter to be visible after the function returns.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
This will print
12
But there are several other useful usages as in the following example to iterate an array of strings and print them to the standard output.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
IMO most common usage is to pass reference to pointer variable
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
You can create multidimensional jagged array using double pointers:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
One common scenario is where you need to pass a null pointer to a function, and have it initialized within that function, and used outside the function. Without multplie indirection, the calling function would never have access to the initialized object.
Consider the following function:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Any function that calls 'initialize(foo*)' will not have access to the initialized instance of Foo, beacuse the pointer that's passed to this function is a copy. (The pointer is just an integer after all, and integers are passed by value.)
However, if the function was defined like this:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...and it was called like this...
Foo* my_foo;
initialize(&my_foo);
...then the caller would have access to the initialized instance, via 'my_foo' - because it's the address of the pointer that was passed to 'initialize'.
Of course, in my simplified example, the 'initialize' function could simply return the newly created instance via the return keyword, but that does not always suit - maybe the function needs to return something else.
If you pass a pointer in as output parameter, you might want to pass it as Foo** and set its value as *ppFoo = pSomeOtherFoo.
And from the algorithms-and-data-structures department, you can use that double indirection to update pointers, which can be faster than for instance swapping actual objects.
A simple example would be using int** foo_mat as a 2d array of integers.
Or you may also use pointers to pointers - lets say that you have a pointer void* foo and you have 2 different objects that have a reference to it with the following members: void** foo_pointer1 and void** foo_pointer2, by having a pointer to a pointer you can actually check whether *foo_pointer1 == NULL which indicates that foo is NULL. You wouldn't be able to check whether foo is NULL if foo_pointer1 was a regular pointer.
I hope that my explanation wasn't too messy :)
Carl: Your example should be:
*p = x;
(You have two stars.) :-)
In C, the idiom is absolutely required. Consider the problem in which you want a function to add a string (pure C, so a char *) to an array of pointers to char *. The function prototype requires three levels of indirection:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
We call it as follows:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
In C++ we have the option of using references instead, which would yield a different signature. But we still need the two levels of indirection you asked about in your original question:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Usually when you pass a pointer to a function as a return value:
ErrorCode AllocateObject (void **object);
where the function returns a success/failure error code and fills in the object parameter with a pointer to the new object:
*object = new Object;
This is used a lot in COM programming in Win32.
This is more of a C thing to do, in C++ you can often wrap this type of system into a class to make the code more readable.

Is it legal to write to a `const T*` through a `T**`?

I'm currently working on a project where I often have to build linked lists of various C structs. Since I don't want to keep repeating myself setting next pointers, I wrote some helper templates, but soon found out that it falls apart if one of the next fields is a pointer-to-const.
My linked list elements look something like this:
struct WorkingElementType {
void *pNext;
/* stuff */
};
struct TroublesomeElementType {
const void *pNext;
/* stuff */
};
In reality, there are of course a lot more of these structs. My helper functions have to keep a pointer to the last element's pNext field in order to write to it when the linked list gets extended, so I went for a void **ppNext = &last->pNext. Unfortunately, that of course breaks down with TroublesomeElementType and its const void *pNext.
In the end, what I'd like to achieve is this:
void **m_ppNext;
/* In one function */
m_ppNext = &last->pNext;
/* In a different function, extending the list */
T *elementToAppend = ...;
*m_ppNext = elementToAppend;
I solved this by using a std::variant<void **, const void **> ppNext instead, but using a std::variant and std::visit just for a difference in constness that doesn't even affect the code's function feels like a bit of a waste.
That's why I'm wondering: Is it legal to use const_cast here to cast away const and stuff the const void ** into a void ** only for updating the pointed-to pointer? No const object actually gets modified, after all.
In other words: I'm not sure whether it's legal to alias const void* and void *. (My gut feeling says no, it's not legal because these are incompatible types, but I don't know for sure.)
The C++ standard in question is C++20.
Here's some simple example code:
#include <variant>
int g_i = 42;
/* This is legal */
void setIntPtr1(std::variant<int **, const int **> v) {
std::visit([](auto& p) { *p = &g_i; }, v);
}
int testNonConst1() {
int *i;
setIntPtr1(&i);
return *i;
}
int testConst1() {
const int *i;
setIntPtr1(&i);
return *i;
}
/* But I'm not sure about this */
void setIntPtr2(int **p) {
*p = &g_i;
}
int testNonConst2() {
int *i;
setIntPtr2(&i);
return *i;
}
int testConst2() {
const int *i;
setIntPtr2(const_cast<int **>(&i)); // Is this legal?
return *i;
}
On Godbolt, all of the various test... functions compile to the exact same assembly, but I don't know if testConst2 is legal C++.
I've found the following two existing questions:
Is it legal to modify any data pointer through a void **
Why isn't it legal to convert "pointer to pointer to non-const" to a "pointer to pointer to const"
However, both of them don't seem to quite answer my question. The first one deals with casting any T** to a void **, which is not what I'm doing; I'm just casting away constness. The second one asks why it's a compile error to convert a void ** to a const void **, but not whether interpreting the memory of a void * as a const void * and vice-versa (without actually overwriting a const object) would be a violation of the aliasing rules.
Yes, it is legal.
[basic.lval]/11:
If a program attempts to access the stored value of an object through a glvalue whose type is not similar to one of the following types the behavior is undefined:
the dynamic type of the object [...]
T* and const T* are similar:
Two types T1 and T2 are similar if they have cv-decompositions with the same n such that corresponding Pi components are either the same or one is "array of Ni" and the other is "array of unknown bound of", and the types denoted by U are the same.

Get the address of a callback function to call dynamically in C++

I am trying to build an application that can dynamically call any Win32 API function according to user input.
I am wondering how can I have behavior of the function RegisterCallback in C++, because it seems very useful and it can get the address to a callback function.
How can I achieve a same behavior with a function like it in C++?
I already successfully implemented a function which can call any dynamic library, but stuck in such dynamic callbacks.
For example I can call EnumWindows API with my function like below:
CallLibFunction(GetProcAddress(LoadLibrary(L"User32.dll"), "EnumWindows"), ParamArray, 2, ExepInfo);
Thanks in advance.
EDIT: I will explain more.
Assume I have following code:
Callback function:
BOOL CALLBACK EnumWindowsProc(__in HWND hWnd, __in LPARAM lParam)
{
return TRUE;
}
Main Function:
EnumWindows(EnumWindowsProc, NULL);
Above is the usual way anyone can use the API function. I want it to be called like this:
LONGLONG CallbackAddress = <Some Function to get address>&EnumWindowsProc
ParamArray[1].type = VT_I8;
ParamArray[1].llval = CallbackAddress; // Address of `EnumWindowsProc`.
And then finally call it dynamically like:
CallLibFunction(GetProcAddress(LoadLibrary(L"User32.dll"), "EnumWindows"), ParamArray, 2, ExepInfo);
First, you need to declare a pointer type to hold the address of your callback. The basic definition of a function is a bit odd in c++. There is a further complication that in C++ we have functions, function-objects, and template types.
The standard provides a basic function template type:std::function. This type
holds not a function pointer, but a callable object.
#include <functional>
To declare a specific function type, pass its signature to std::function as its template parameter.
typedef std::function<int(const char*)> StdFreeFunc;
// you can also define types for member functions, and define
// member function pointers this way
struct A{};
typedef std::function<int A::*(const char*)> StdMemberFunc;
// member callable objects are called with this syntax:
// (obj.*callable)(args); or (obj->*callable)(args);
// the parenthesis are often required to keep the compiler happy
// A callable object:
struct CallMe
{
int xy;
int operator()(const char*) { /*...*/ return xy; }
};
std::function is compatible with function objects, lambdas and regular function pointers (see below). Works best with C++ only stuff.
struct AStruct
{
StdFreeFunc callback_; // we hold a value, not a pointer
void setCallback(StdFreeFunc&& cb) // pass by value, reference, const ref,
{ // move... like any object type
callback_ = cb;
};
int callCallback(const char* str)
{
if (callback_) // callable object has a bool() operator to check if valid !!
return (callback_)(str);
// the parenthesis and is optional, so this is the same:
if (callback_)
return callback_(str):
}
};
// example with callable object:
AStruct as, ar;
as.setCallback(CallMe{42}); // we can pass an object with data
ar.setCallback(CallMe{84}); // to obtain different effects
as.callCallback("prints fourty two");
ar.callCallback("prints eighty four");
C-style function pointers
Before C++, there was C. THis is how it's done in C, and it does compile. The disadvantage with C-style function pointers is that they are not compatible with function objects. On the other hand they are compatible with C, and many other languages such as PASCAL, VB, etc..
For example, the type a function taking a const char* as a parameter and returning an int is written as:
typedef int (CallBack)(const char*);
The most usual form is to declare a pointer, since that's what is stored. As in:
typedef int (*CallBack)(const char*);
// you can specify extra call specifications
typedef int (__stdcall * CallBack)(const char*); // uses PASCAL calling
// exmample:
struct YourStruct
{
//...
Callback callback_{nullptr}; // this is a pointer initialize to nullptr
//...
void setCallback(Callback cb)
{
// call as ys.setCallback(AFunction)
// or ys.setCallback(&AFunction)
callback_ = cb;
};
int callCallback(const char* str)
{
if (callback_) // always check if valid !!
return (*callback_)(str);
// the parenthesis and the * are optional, so this is the same:
if (callback_)
return callback_(str):
}
};
int UserFunction(const char*) { /*...*/ return 0; }
YourStruct ys;
ys.setCallback(&UserFunction);
ys.callCallback("hello");
Reading your link, the following is said about the callback address:
If the exe running the script is 32-bit, this parameter must be between 0 and 4294967295. If the exe is 64-bit, this parameter can be a 64-bit integer.
So, you need to convert your pointer address to an integer type. Drawing some inspiration from this answer, the following code should give you a hint how to do the conversion in your case:
#include <iostream>
#include <cstdint>
bool f() {
return true;
}
int main() {
int iv = *((int*)(&f));
long lv = *((long*)(&f));
long long llv = *((long long*)(&f));
intptr_t ipv = *((intptr_t*)(&f));
std::cout << "int: " << iv << std::endl;
std::cout << "long: " << lv << std::endl;
std::cout << "long long: " << llv << std::endl;
std::cout << "intptr_t: " << ipv << std::endl;
}
For me this prints:
int: -443987883
long: 82192552476362837
long long: 82192552476362837
intptr_t: 82192552476362837
Note here that an int is to small to cover the void* value. You should be able to convert properly with LONGLONG as well, otherwise intptr_t seems to be the correct data type.

Callback functions with different arguments

I have two functions with a little different functionality, so I can't make them as template functions.
int func64(__int64 a) {
return (int) a/2;
}
int func32(int a) {
return a--;
}
Depending on variable b64, I would like to call func64 or func32. I don't want check if b64 is true many times in my code, so I use pointers to functions.
void do_func(bool b64) {
typedef int (*pfunc32)(int);
typedef int (*pfunc64)(__int64);
pfunc32 call_func;
if (b64)
call_func = func64; //error C2440: '=' : cannot convert from 'int (__cdecl *)(__int64)' to 'pfunc32'
else
call_func = func32;
//...
call_func(6);
}
How can I avoid this error and cast call_func to pfunc32 or pfunc64?
The language requires all functions called through the same function pointer to have the same prototype.
Depending on what you want to achieve, you could use the pointer/cast aproach already mentioned (which satisfies this requirement at the loss of type safety) or pass a union instead:
union u32_64
{
__int64 i64;
int i32;
};
int func64(union u32_64 a) {
return (int) a.i64/2;
}
int func32(union u32_64 a) {
return --a.i32;
}
void do_func(bool b64) {
typedef int (*pfunc)(union u32_64);
pfunc call_func;
if (b64)
call_func = func64;
else
call_func = func32;
//...
union u32_64 u = { .i64 = 6 };
call_func(u);
}
Pass a void pointer and cast it in the function body.
Of course this means less compiler control if you use the wrong type; if you call func64 and pass an int to it the program will compile and produce wrong results without giving you any tip of what is going wrong.
int func64(void *a) {
__int64 b = *((__int64*) a);
return (int) b/2;
}
int func32(void *a) {
int b = *((int *) a)
return b-1;
}
I need to call func32() or func64() depending on flag b64
So do that:
void do_func(bool b64) {
if (b64)
func64(6);
else
func32(6);
}
Well, first of all, please note that function func32 is returning the input argument as is.
This is because with return a--, you are returning the value of a before decrementing it.
Perhaps you meant to return a-1 instead?
In any case, you can simply declare this function as int func32(__int64 a).
This way, it will have the same prototype as function func64, but will work exactly as before.
BTW, calling a function through a pointer might be more "expensive" than a simple branch operation, so depending on your application, you might be better off with a simple if/else conditional statement...
Make a wrapper for func64:
int func64_as_32(int a) {
return func64(a);
}
Now you can assign either func32 or func64_as_32 to call_func since they have the same signature. The value you pass in, 6, has type int so passing it to func64_as_32 has the same effect as passing it directly to func64.
If you have call sites where you pass in a value of type __int64 then you'd do it the other way around, wrap func32.
As bool in C++ converts to int ( true => 1, false => 0 ) you can use b64 as array index. So take SJuan76's advice, convert your functions prototype to int f(void*) and put them into array int (*array_fun[2])(void* x); . You can call these functions then like that :
int p = 6;
array_fun[b64](&p);

To what use is multiple indirection in C++?

Under what circumstances might you want to use multiple indirection (that is, a chain of pointers as in Foo **) in C++?
Most common usage as #aku pointed out is to allow a change to a pointer parameter to be visible after the function returns.
#include <iostream>
using namespace std;
struct Foo {
int a;
};
void CreateFoo(Foo** p) {
*p = new Foo();
(*p)->a = 12;
}
int main(int argc, char* argv[])
{
Foo* p = NULL;
CreateFoo(&p);
cout << p->a << endl;
delete p;
return 0;
}
This will print
12
But there are several other useful usages as in the following example to iterate an array of strings and print them to the standard output.
#include <iostream>
using namespace std;
int main(int argc, char* argv[])
{
const char* words[] = { "first", "second", NULL };
for (const char** p = words; *p != NULL; ++p) {
cout << *p << endl;
}
return 0;
}
IMO most common usage is to pass reference to pointer variable
void test(int ** var)
{
...
}
int *foo = ...
test(&foo);
You can create multidimensional jagged array using double pointers:
int ** array = new *int[2];
array[0] = new int[2];
array[1] = new int[3];
One common scenario is where you need to pass a null pointer to a function, and have it initialized within that function, and used outside the function. Without multplie indirection, the calling function would never have access to the initialized object.
Consider the following function:
initialize(foo* my_foo)
{
my_foo = new Foo();
}
Any function that calls 'initialize(foo*)' will not have access to the initialized instance of Foo, beacuse the pointer that's passed to this function is a copy. (The pointer is just an integer after all, and integers are passed by value.)
However, if the function was defined like this:
initialize(foo** my_foo)
{
*my_foo = new Foo();
}
...and it was called like this...
Foo* my_foo;
initialize(&my_foo);
...then the caller would have access to the initialized instance, via 'my_foo' - because it's the address of the pointer that was passed to 'initialize'.
Of course, in my simplified example, the 'initialize' function could simply return the newly created instance via the return keyword, but that does not always suit - maybe the function needs to return something else.
If you pass a pointer in as output parameter, you might want to pass it as Foo** and set its value as *ppFoo = pSomeOtherFoo.
And from the algorithms-and-data-structures department, you can use that double indirection to update pointers, which can be faster than for instance swapping actual objects.
A simple example would be using int** foo_mat as a 2d array of integers.
Or you may also use pointers to pointers - lets say that you have a pointer void* foo and you have 2 different objects that have a reference to it with the following members: void** foo_pointer1 and void** foo_pointer2, by having a pointer to a pointer you can actually check whether *foo_pointer1 == NULL which indicates that foo is NULL. You wouldn't be able to check whether foo is NULL if foo_pointer1 was a regular pointer.
I hope that my explanation wasn't too messy :)
Carl: Your example should be:
*p = x;
(You have two stars.) :-)
In C, the idiom is absolutely required. Consider the problem in which you want a function to add a string (pure C, so a char *) to an array of pointers to char *. The function prototype requires three levels of indirection:
int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add);
We call it as follows:
unsigned int the_count = 0;
char **the_list = NULL;
AddStringToList(&the_count, &the_list, "The string I'm adding");
In C++ we have the option of using references instead, which would yield a different signature. But we still need the two levels of indirection you asked about in your original question:
int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add);
Usually when you pass a pointer to a function as a return value:
ErrorCode AllocateObject (void **object);
where the function returns a success/failure error code and fills in the object parameter with a pointer to the new object:
*object = new Object;
This is used a lot in COM programming in Win32.
This is more of a C thing to do, in C++ you can often wrap this type of system into a class to make the code more readable.