Home > Blockchain >  Function Pointer using "typedef" keyword with Function Address stored as Variable? (C 14
Function Pointer using "typedef" keyword with Function Address stored as Variable? (C 14

Time:08-02

Problem Summary

I'm attempting to create a callable function pointer inside of a function using templates for its return value and its arguments using C 14. I want the callable function pointer to return the templated type, and accept templated arguments. However, I also want the callable function pointer to point to an existing function at the address provided in an argument as an integer. This I am unsure of how to do. Below is an illustration of my current incomplete code:

template <class retTempl, class argTempl_1, class argTempl_2>
retTempl TEST_1(argTempl_1 value1, argTempl_2 value2, int addr) {

    typedef retTempl(*TEST_2)(argTempl_1, argTempl_2);
    return TEST_2(value1, value2);

}

In this case, TEST_2 is the new function pointer that I want to call, and the addr argument is the address of an existing function that I want the TEST_2 pointer to point to.

The current error that the VS 2019 compiler throws at me is the following:

Error   C2440   '<function-style-cast>': cannot convert from 'initializer list' to 'operationFunction'

I am unsure of exactly what it's trying to tell me, researching this error online leads to several possible causes, not all of which necessarily have to do with function pointers. However, this error may not even be relevant, as I have not been able to implement the function address yet. That is mostly what I want to focus on here.

My Attempts

I know that in order to make a function pointer created with the typedef keyword point to an actual function, you need to set the pointer variable equal to whichever function you want the pointer to point to. So for instance (example from https://www.section.io/engineering-education/function-pointers-in-c /):

int add(int x ,int y)  
{  
    return x   y;  
}  
int main()  
{  
 int (*funcptr)(int, int);
 funcpointr = add;

 ...
}

However, here the function that I want the TEST_2 pointer to point to is different every time that TEST_1 is called, with a different return value and arguments. Therefore, I cannot simply set the TEST_2 variable equal to the addr argument:

template <class retTempl, class argTempl_1, class argTempl_2>
retTempl TEST_1(argTempl_1 value1, argTempl_2 value2, int addr) {

    typedef retTempl(*TEST_2)(argTempl_1, argTempl_2);
    TEST_2 = addr;
    return TEST_2(value1, value2);

}

as this now supplies me with an additional VS error:

Error   C2513   'retTempl (__cdecl *)(argTempl_1,argTempl_2)': no variable declared before '='

I would assume that I would require another pointer variable here, perhaps from a list of function pointers that I want the TEST_2 variable to point to, but at this point I would like to hear a second opinion before I resume.

Is what I'm trying to achieve here even possible to do with C ? Is there a different way that this should be done that I'm not aware of?

Thank you in advance for reading my post, any guidance is appreciated!

CodePudding user response:

After a lot of research, and posting this question on other programming forums, I reached an answer, and several other conclusions that I believe are worth sharing in regards to my original problem (very informative answers provided to me on this forum: https://cplusplus.com/forum/general/284539/).

Immediate Solution

The immediate issue in my original code was the fact that I mistakenly assumed that the typedef keyword creates an object, instead of an object type. What should have been done was to create an object instance of the type created with the typedef keyword (huge thanks to the people in the comments of my original post here for pointing this out). So:

TEST_2 test_function;

Following the creation of the object instance with the type of the function pointer, I have the argument addr of type int that holds the address of the function I want the TEST_2 pointer variable to point to. While the use of variables of size int isn't the best way to store function addresses (as int isn't large enough to store all formats of function addresses, and could result in other issues with the pointer), if you are forced to retrieve your function from an int variable, then you would need to typecast the address variable to your function pointer type in the variable you have created. So:

TEST_2 test_function = (TEST_2)(addr);

or

TEST_2 test_function = reinterpret_cast<TEST_2>(addr);

So the whole original function being:

template <class retTempl, class argTempl_1, class argTempl_2>
retTempl TEST_1(argTempl_1 value1, argTempl_2 value2, int addr) {

    typedef retTempl(*TEST_2)(argTempl_1, argTempl_2);
    TEST_2 test_function = (TEST_2)(addr);
    return test_function(value1, value2);

}

This now worked on my end to call my desired function, and to return the correct variable and type. However...

Proper Solution

As stated previously, using a variable of size int is not ideal for storing function addresses. There is a variable type designed to store addresses, uintptr_t, however this type of variable is only designed to store object addresses, not function ones.

The proper way to do this would be to always store your function pointers exclusively as pointer types, such as void(*)(), to avoid any discrepancies with the function addresses. If there really is a need to store function addresses in variables, then it would be ideal to use memcpy, instead of casting, to achieve this (although I have not experimented with this as of now).

Thank you to everyone who helped me out with this issue!

  • Related