Function Pointer basic question - c++

I have a basic question on function pointer.
In the below code snippet, how do I read this "
*(FARPROC*)&pfn ="?
IFastString *CallCreateFastString(const char *psz) {
static IFastString * (*pfn)(const char *) = 0;
if (!pfn) {
const TCHAR szDll[] = _TEXT("FastString.DLL");
const char szFn[] = "CreateFastString";
HINSTANCE h = LoadLibrary(szDll);
if (h)
*(FARPROC*)&pfn = GetProcAddress(h, szFn);
}
return pfn ? pfn(psz) : 0;
}

This isn't really about function pointers, but about casting in general.
Suppose pfn is of type T. Then &pfn is of type T*. This gets cast to FARPROC* by the cast expression (the stuff in the parentheses). Finally, this gets dereferenced, yielding a FARPROC&.
All in all this just means you're treating pfn as if it were of type FARPROC and assign a value to it.
Here's a generic example:
S make_an_S();
T x;
T * const px = &x;
S * const py = (S*)px;
*py = make_an_S(); // same as *(S*)&x = make_an_S();

*(FARPROC*)&pfn = GetProcAddress(h, szFn);
is equivalent to,
(FARPROC)pfn = GetProcAddress(h, szFn);
So, pfn is a function pointer which is type casted to FARPROC to store the address received from GetProcAddress(h, szFn).
[Note: I am not sure, if this kind of typecasting is deprecated in C++.]

Related

How to transform function to lambda function

I have function:
FARPROC PUDSClass::getFunction(LPSTR szName)
{
if(handleDLL == NULL)
{
return NULL;
}
return GetProcAddress(handleDLL, szName);
}
I am trying to rewrite it as lambda function.
FARPROC lambda_decToStrHex = [&](LPSTR szName)
{
if (handleDLL == NULL)
{
return NULL;
}
return GetProcAddress(handleDLL, szName);
};
But I get error of inconsistent types "int" and "int (attribute(stdcall)*)()".
If I write it like this, it works ok:
auto getFunction = [&](LPSTR szName)
{
return GetProcAddress(handleDLL, szName);
};
From what I understood, lambda cannot handle return NULL or GetProcAddress(), but why can a normal function do so?
FARPROC lambda_decToStrHex = ...;
This will create a variable lambda_decToStrHex, it's type is FARPROC, which, according to documentation, is defined as
int (FAR WINAPI * FARPROC) ()
It is a function returning int and accepting no parameters. This simply doesn't match the type of your lambda.
If at all, you need a function pointer of correct type the lambda can decay to, a function accepting a C string and returning a FARPROC pointer (in short: pointer to function returning function pointer):
FARPROC (*lambda_decToStrHex)(LPSTR) = ...;
Solely: Your lambda cannot decay to a function pointer, as it has a non-empty closure:
... = [&](LPSTR name) { /* ... */ };
// ^ ^ uses dllHandle, which thus gets part of closure
So all that remains is assigning the lambda to a variable thetype of your lambda, which you get by auto.
Edit: return NULL;:
'Lambda' is a red herring here, it is not an issue of lambdas, but of any function having deduced return type (auto f() { ... }). NULL typically is defined as (void*)0, (but can look differently as well), so you get two different return types (void* and FARPROC) at the two exit points of the (in this case) lambda. Which return type should now be deduced?
At very first, you shouldn't be using NULL at all any more, it is a macro coming from C, whereas C++ provides a keyword for: nullptr. Solely, it won't solve the issue, as it has it's own type (std::nullptr_t) which still differs from FARPROC. A cast then can solve the issue (that actually would work with the macro as well):
return static_cast<FARPROC>(nullptr);
Now both exit points have the same return type and we are fine. A trailing return type achieves the same:
[&](LPSTR) -> FARPROC { ... }
nullptr automatically decays to correct pointer type (so you don't need a cast); NULL macro, without a cast and depending on how being defined, can (but needn't) fail, though.
Another solution would be one single, well defined exit point:
[&](LPSTR)
{
FARPROC function = nullptr;
if(dllHandle)
function = get();
return function;
}
Why did it work with the normal function then? Well, you explicitly specified the return type (FARPROC f(...)), which is equivalent to having a trailing return type. Additionally, the fact that it compiled and the error message:
"int" and "int (attribute(stdcall)*)()"
^^^
reveal that your compiler obviously defines NULL without the void* cast:
#define NULL 0
or similar – and 0 literal decays to null pointer as well...
Since you specify the return type FARPROC in normal function, NULL (0, which is int type) will implicitly convert to FARPROC type (which is int (attribute(stdcall)*)()).
You can using using -> to specify the return type with lambda:
auto lambda_decToStrHex = [&](LPSTR szName) -> FARPROC
{
if (handleDLL == NULL)
{
return NULL;
}
return GetProcAddress(handleDLL, szName);
};

How do I cast int** to void**?

With the following snippet:
int n = 11;
int* c = &n;
void** v = &c;
I receive the following error in visual studio:
the value of type int** cannot be used to initialize an entity of type void **.
This works fine:
int n = 11;
int* c = &n;
void* v = c;
But this code snippet is for a larger problem in someone's library.
What am I doing wrong with casting a variable to void**?
Complete Example
Using the caen digitizer library the way they try to collect data from the peripheral device has this prototype:
/******************************************************************************
* X742_DecodeEvent(char *evtPtr, void **Evt)
* Decodes a specified event stored in the acquisition buffer writing data in Evt memory
* Once used the Evt memory MUST be deallocated by the caller!
*
* [IN] EventPtr : pointer to the requested event in the acquisition buffer (MUST BE NULL)
* [OUT] Evt : event structure with the requested event data
* : return 0 = Success;
******************************************************************************/
int32_t X742_DecodeEvent(char *evtPtr, void **Evt);
And this is the implementation:
int32_t X742_DecodeEvent(char *evtPtr, void **Evt) {
CAEN_DGTZ_X742_EVENT_t *Event;
uint32_t *buffer;
char chanMask;
uint32_t j,g,size;
uint32_t *pbuffer;
uint32_t eventSize;
int evtSize,h;
evtSize = *(long *)evtPtr & 0x0FFFFFFF;
chanMask = *(long *)(evtPtr+4) & 0x0000000F;
evtPtr += EVENT_HEADER_SIZE;
buffer = (uint32_t *) evtPtr;
pbuffer = (uint32_t *) evtPtr;
eventSize = (evtSize * 4) - EVENT_HEADER_SIZE;
if (eventSize == 0) return -1;
Event = (CAEN_DGTZ_X742_EVENT_t *) malloc(sizeof(CAEN_DGTZ_X742_EVENT_t));
if (Event == NULL) return -1;
memset( Event, 0, sizeof(CAEN_DGTZ_X742_EVENT_t));
for (g=0; g<X742_MAX_GROUPS; g++) {
if ((chanMask >> g) & 0x1) {
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j]= malloc(X742_FIXED_SIZE * sizeof (float));
if (Event->DataGroup[g].DataChannel[j] == NULL) {
for (h=j-1;h>-1;h++) free(Event->DataGroup[g].DataChannel[h]);
return -1;
}
}
size=V1742UnpackEventGroup(g,pbuffer,&(Event->DataGroup[g]));
pbuffer+=size;
Event->GrPresent[g] = 1;
}
else {
Event->GrPresent[g] = 0;
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j] = NULL;
}
}
}
*Evt = Event;
return 0;
}
I use this by:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL; // Creating my event pointer
//Doing some config of the device
X742_DecodeEvent(evtptr, &Evt); //Decode the event data for me to read (Throws error)
Hope this gives some context.
void** means a pointer to a void* object. But there is no void* object in that code to point at! void** does NOT mean "a pointer to any kind of pointer", so please avoid using it as such. If you have a pointer to something which might be an int*, might be a double*, or etc., void* is a better type than void**. Even better would be a template or std::variant or std::any.
But if you have to use a library that is using void** to mean "a pointer to a pointer to a type unknown at compile time" or something like that, you might need to create a void* pointer to work with, or might need to add in casts to get around the fact that the compiler doesn't like this conversion (for good reason). The problem is, there are at least two reasonable ways to do this! (They will end up doing exactly the same thing on many common computer architectures, but this is not guaranteed.)
// LibraryFunc1 takes a void** argument that somehow means an int* pointer.
// But which call is correct?
int* data_in = generate_data();
LibraryFunc1(reinterpret_cast<void**>(&data_in)); // ?
void* p1 = data_in;
LibraryFunc1(&p1); // ?
// LibraryFunc2 returns a void** argument that somehow means an int* pointer.
void** p2 = LibraryFunc2();
int* data_out_1 = static_cast<int*>(*p2); // ?
int* data_out_2 = *reinterpret_cast<int**>(p2); // ?
Based on the function definition shown, the safe usage is unfortunately:
void* tmpEvt;
X742_DecodeEvent(evtptr, &tmpEvt);
auto* Evt = static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
since the library function assumes at *Evt = Event; that *Evt is actually a void* object it can modify. It may usually work to do the simpler thing instead:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL;
X742_DecodeEvent(evtptr, reinterpret_cast<void**>(&Evt));
but this is undefined behavior by the C++ Standard, and might do the wrong thing on some architectures.
You could make the correct way easier by wrapping it in a function:
inline CAEN_DGTZ_X742_EVENT_t* Get_X742_DecodeEvent(char* evtPtr)
{
void* tmpEvt;
X742_DecodeEvent(evtPtr, &tmpEvt);
return static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
}
What am I doing wrong with casting a variable to void**?
There is no meaningful way to convert int** to void**, so what you're trying to do is wrong.
What you may do is
int n = 11;
void* c = &n;
void** v = &c;
But without a complete example, it is not possible to say whether applies to your problem.
That's simply how the language works.
void * pointers get special treatment: a pointer to an arbitrary type can be converted to a pointer to void (as long as doing so doesn't remove cv-qualifiers from the pointer).
void ** gets none of that special treatment. It's just a regular pointer type, like int **.
int32_t X742_DecodeEvent(char *evtPtr, void **Evt)
Since you want to pass CAEN_DGTZ_X742_EVENT_t ** to your function, you should change the parameter type accordingly: CAEN_DGTZ_X742_EVENT_t **Evt.
In comments you were suggested to use void ** v = (void**)&c;.
While you could probably make it work in practice, strictly speaking any access to *v would violate strict aliasing and cause undefined behavior. I wouldn't use that solution.

Converting C to CPP with Function Pointers

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;
}

Using void in functions. Won't recognise

I'm having a problem with this function. The function is supposed to return a type of StoredData.
This is my struct:
struct StoredData
{
void* data;
int size;
int type;
int compareValue;
StoredData():
size(0),
type(0),
compareValue(0){}
};
And this is my function:
StoredData SDI::Array::create(int size, int type, int compareValue)
{
StoredData temp;
void* data;
int input;
int input2;
std::cout<<"What type of data would you like to insert?"<<std::endl;
std::cout<<"1 - Integer"<<std::endl;
std::cout<<"2 - Boolean"<<std::endl;
std::cin>>input;
std::cout<<"What is the value?"<<std::endl;
std::cin>>input2;
switch (input)
{
case 1:
size = sizeof(int);
type = 0;
data = new int;
*data = (int)input2;
break;
case 2:
size = sizeof(bool);
type = 1;
data = new bool;
*data = (bool)input2;
break;
}
temp.compareValue=input2;
temp.data = data;
temp.type = type;
temp.size = size;
}
Unfortunately, I'm having a problem with the line within the case statements with
*data = (bool)input2;
The error that I'm getting is that it must be a pointer to a complete object type. I need the void variable to recognize the data, and I'm getting no luck. Anybody know a workaround?
I'm getting 2 error messages for each. The first is,
illegal indirection
And the second ones are,
error C2440: '=' : cannot convert from 'int' to 'void *'
error C2440: '=' : cannot convert from 'bool' to 'void *'
You can't dereference a void pointer. You will have to cast it to a pointer type you can dereference:
*(bool *) data = (bool) input2;
You are attempting to dereference a void pointer and set its value:
*data = (bool)input2;
This is meaningless to the compiler. What type will the result of *data be?
You need to cast the void* to something meaningful first:
*(bool*)data = (bool)input2;
Alternatively, you could initialize your dynamic variables with the correct values when you create them:
data = new int(input2);
...
data = new bool(input2);
Which wouldn't require you to cast anything.
void is an incomplete type.You may not create objects of incomplete type.
You can't dereference a plain void*, as it could point to basically anything. You aither have to make it point to something other (assigning to another pointer):
bool* bool_pointer = new bool;
*bool_pointer = static_cast<bool>(input2);
data = bool_pointer;
Or use typecasting:
*reinterpret_cast<bool*>(data) = static_cast<bool>(input2);

C++: Const correctness and pointer arguments

I understand that a const pointer can be declared a couple ways:
const int * intPtr1; // Declares a pointer that cannot be changed.
int * const intPtr2; // Declares a pointer whose contents cannot be changed.
// EDIT: THE ABOVE CLAIMS ARE INCORRECT, PLEASE READ THE ANSWERS.
But what about the same principles within the context of function arguments?
I would assume that the following is redundant:
void someFunc1(const int * arg);
void someFunc2(int * arg);
Since someFunc 1 and 2 do a pass-by-value for the pointer itself, its impossible for someFunc1 to change the value of the original pointer, in a given call to the function. To illustrate:
int i = 5;
int * iPtr = &i;
someFunc1(iPtr); // The value of iPtr is copied in and thus cannot be changed by someFunc1.
If these are true, then there is no point in ever declaring a function with a 'const int * ptr' type arg, correct?
You have it backwards:
const int * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
The following const is indeed unnecessary, and there's no reason to put it in a function declaration:
void someFunc1(int * const arg);
However, you might want to put it in the function implementation, for the same reason that you might want to declare a local variable (or anything else) const - the implementation may be easier to follow when you know that certain things won't change. You can do that whether or not it's declared const in any other declarations of the function.
Well it is not meant for the caller but for the code inside the someFunc1. So that any code inside someFunc1 wont accidentally change it. like
void someFunc1(int *arg) {
int i = 9;
arg = &i; // here is the issue
int j = *arg;
}
Lets do some case study:
1) Just making the pointed value const
void someFunc1(const int * arg) {
int i = 9;
*arg = i; // <- compiler error as pointed value is const
}
2) Just making the pointer const
void someFunc1(int * const arg) {
int i = 9;
arg = &i; // <- compiler error as pointer is const
}
3) Right way to use const if variables involved can be const:
void someFunc1(const int * const arg) {
int i = 9;
*arg = i; // <- compiler error as pointed value is const
arg = &i; // <- compiler error as pointer is const
}
This should clear all doubts. So I already mentioned it is meant for the function code and not for the caller and you should use the most restrictive of the 3 cases i mentioned above.
EDIT:
Even in declarations of functions its a good practice to declare const. This will not only increase readability but also the caller will be aware of the contract and has more confidence regarding immutability of arguments. (This is required bcoz you generally share your header files so caller might not have your implementation c/cpp file)
Even compiler can point out better if both declaration and definitions are in sync.
You've got your logic the wrong way round. You should read the type backwards, so const int * is a pointer to a const int and int * const is a const pointer to an int.
Example:
void foo() {
int a = 0;
int b = 0;
int * const ptrA = &a;
*ptrA = 1;
ptrA = &b; ///< Error
const int * ptrB = &a;
*ptrB = 1; ///< Error
ptrB = &b;
const int * const ptrC = &a;
*ptrC = 1; ///< Error
ptrC = &a; ///< Error
}
To elaborate and show why you would want your function parameter to be a const int * you might want to indicate to the caller that they must pass in an int because you as a function want to change the value. Consider this code for instance:
void someFunc1(const int * arg) {
// Can't change *arg in here
}
void someFunc2(int * arg) {
*arg = 5;
}
void foo() {
int a = 0;
someFunc1(&a);
someFunc2(&a);
const int b = 0;
someFunc1(&b);
someFunc2(&b); ///< *** Error here. Must pass in an int not a const int.
}
Yes, you are correct (ignoring the fact that you got them the wrong way around)- there is no sense in taking non-reference const parameters. In addition, there is no sense in returning non-reference const values.
You have it the wrong way:
const int * intPtr1; // Declares a pointer whose contents cannot be changed.
int * const intPtr2; // Declares a pointer that cannot be changed.
Generally speaking its easier to reason about constness when writting that expression slightly different: const int* is the same type as int const *. In that notation the rules are much clearer, const always applies to the type preceding it, therefore:
int const * intPtr1; // Declares a pointer to const int.
int * const intPtr2; // Declares a const pointer to int.
int const * * const * complexPtr; // A pointer to const pointer to pointer to const int
When the type is written with a leading const, the const is handled as if it was written after the first type, so const T* becomes T const *.
void someFunc2(int * arg);
Is therefore not redundant, since someFunc2 may change the contents of arg, while someFunc1 may not. void someFunc3(int * const arg); would be redundant (and ambigous) though