Callback: function pointer as argument and passing an aditional agrument [duplicate] - c++

This question already has answers here:
Explanation of function pointers
(4 answers)
Closed 2 years ago.
How to pass a function pointer as argument with an argument?
void A(){
std::cout << "hello" << endl;
}
void B(void (*ptr)()){ // function pointer as agrument
ptr(); // call back function "ptr" points.
}
void C(string name){
std::cout << "hello" << name << endl;
}
void D(void (*ptr2)(string name)){ // function pointer as agrument
ptr2(name); // error 1
}
int main(){
void (*p)() = A; // all good
B(p); // is callback // all good
void (*q)(string name) = C;
D(q)("John Doe"); // error 2
return 0;
};
errors:
1 - use of undeclared identifier 'name'
2 - called object type 'void' is not a function or function pointer

You should make D taking two parameters, one for the function pointer, one for the argument to be passed to function pointer. E.g.
void D(void (*ptr2)(string), const string& name){
ptr2(name);
}
then call it like
D(q, "John Doe");

name is a part of type declaration for ptr2 and is not a variable in D.
Tou are trying to call what is returned from D, which is void. , is used to separate arguments in C++.
Try this:
#include <iostream>
#include <string>
using std::endl;
using std::string;
void A(){
std::cout << "hello" << endl;
}
void B(void (*ptr)()){ // function pointer as agrument
ptr(); // call back function "ptr" points.
}
void C(string name){
std::cout << "hello" << name << endl;
}
void D(void (*ptr2)(string name), string name){ // function pointer and a string as agrument
ptr2(name);
}
int main(){
void (*p)() = A; // all good
B(p); // is callback // all good
void (*q)(string name) = C;
D(q, "John Doe"); // pass 2 arguments
return 0;
} // you don't need ; here

Related

How to call a function from a function pointer? [duplicate]

This question already has answers here:
Function pointer as parameter
(3 answers)
Closed 6 months ago.
How can you call a function from only a pointer to the function? For example:
void print()
{
std::cout << "Hello World!" << std::endl;;
}
void run_func(void* func)
{
func(); // what im trying to do (doesnt actually work)
}
int main()
{
run_func(print);
}
Expected output:
Hello World!
It's a bit like how std::thread creates a thread from the pointer of a variable.
Function pointers in function parameter lists need to be wrapped in parentheses. Change the one line, either by wrapping with parentheses or using the typedef'ed function parameter, and your sample works.
// Simplifies arcane function parameter synax.
typedef void (*FUNC_TO_RUN)();
void print()
{
std::cout << "Hello World!" << std::endl;;
}
// Change your parameter as follows. You need to wrap function
// pointers in parantheses.Or, use a typedef.
// void run_func(void *func())
// void run_func(void (*func)()) // Works, but harder to read
void run_func(FUNC_TO_RUN func) // Works, easier to read
{
func(); // what im trying to do (and now works)
}
int main()
{
run_func(print);
}
You have to change your parameter type of run_func to void (*func) (), which means func is a pointer to a void function that takes no parameters.
Corrected code:
void print() {
std::cout << "Hello World!\n";
}
void run_func(void (*func)()) {
func();
// or you can call the print function by (*func)();
}
int main() {
run_func(print);
// prints "Hello World!"
}
You could use std::function:
void print()
{
std::cout << "Hello World!" << std::endl;;
}
void run_func(std::function<void()> f) // f returns void and takes no parameters
{
f();
}
int main()
{
run_func(print);
}

How can I call a function from an array of functions via its index?

A beginner's question I couldn't find answered online, likely because I don't know the terminology.
I want to call one of a list of procedures based on a computed index value. That is, given a '1', invoke firstProc(), '2' invokes secondProc() and so on.
All the procedures are void functions with no arguments.
I can implement that with switch/case, but what I'd prefer is something like:
void* action[2] {*firstProc, *secondProc};
(This compiles, but warns: invalid conversion from 'void (*)()' to 'void*')
and then later:
action[get_index()]();
The compiler objects that 'action' can't be used as a function.
This must be possible, right? I've tried several variations but I can't get past the use of the selected ('action[index]') as a function.
There are two equivalent ways to do what you want. The explanation is given as comments in the code snippets.
Method 1
#include <iostream>
void foo()
{
std::cout << "Hello";
}
void foo2()
{
std::cout << " wolrd!";
}
int main()
{
void (*a)() = foo;// a is a pointer to a function that takes no parameter and also does not return anything
void (*b)() = foo2;// b is a pointer to a function that takes no parameter and also does not return anything
//create array(of size 2) that can hold pointers to functions that does not return anything and also does not take any parameter
void (*arr[2])() = { a, b};
arr[0](); // calls foo
arr[1](); //calls foo1
return 0;
}
Method 1 can be executed here.
In method 1 above void (*a)() = foo; means that a is a pointer to a function that takes no parameter and also does not return anything.
Similarly, void (*b)() = foo2; means that b is a pointer to a function that takes no parameter and also does not return anything.
Next, void (*arr[2])() = { a, b}; means that arr is an array(of size 2) that can hold pointers to functions that does not return anything and also does not take any parameter.
Method 2
#include <iostream>
void foo()
{
std::cout << "Hello";
}
void foo2()
{
std::cout << " wolrd!";
}
int main()
{
//create array(of size 2) that can hold pointers to functions that does not return anything
void (*arr[2])() = { foo, foo2};
arr[0](); // calls foo
arr[1](); //calls foo1
return 0;
}
Method 2 can be executed here.
You need the correct syntax for your function pointer array. void(*func_ptr[])().
Example:
void func1() { std::cout << "Hallo" << std::endl; }
void func2() { std::cout << "World" << std::endl; }
// if you need a different signature for your functions like:
int func3(int n) { std::cout << "n1 " << n << std::endl; return n*2; }
int func4(int n) { std::cout << "n2 " << n << std::endl; return n*3; }
int main()
{
// array of function pointer which
// have no parameter and void as return value
void(*func_ptr[])()={ func1, func2 };
for ( unsigned int idx = 0; idx<2; idx++ )
{
func_ptr[idx]();
}
// array of function pointers with int return value and int as
// parameter
int(*func_ptr2[])(int)={ func3, func4 };
for ( unsigned int idx = 0; idx<2; idx++ )
{
std::cout << "retval: " << func_ptr2[idx](6) << std::endl;
}
}
I've stopped using function pointers (though they still can be useful).
I usually use std::function (and lambdas) when working with functions
Code for arrays of functions then look like this.
I used std::vector but std::array for fixed size should work fine too.
#include <vector>
#include <functional>
#include <iostream>
void some_function()
{
std::cout << "some function\n";
}
int main()
{
// std::function, abstraction of a function, function signature = template parameter, so void () is function returning a void, no parameters
// std::vector, runtime resizable array
// constructor : 4 time a lambda function printing out hello world.
std::vector<std::function<void()>> functions(4, [] { std::cout << "Hello World!\n"; } );
// easy syntax to assign an existing function to an index
functions[1] = some_function;
// replace a function in the vector with another one (lambda)
functions[2] = [] { std::cout << "booh\n"; };
// call function at index 0
functions[0]();
std::cout << "\n\n";
// or loop over all the functions and call them (classic for loop)
for (std::size_t n = 0; n < functions.size(); ++n) functions[n]();
std::cout << "\n\n";
// or loop over all the functions (range based for loop)
for (const auto& function : functions) function();
return 0;
}

Cannot pass shared_ptr argument to function pointer

I have a problem with the code that uses function pointer that takes shared_ptr argument.
Here is a sample code.
header.h
#include <functional>
#include <iostream>
template <class T> class FuncWrapper{
private:
void (*original_function)(T a);
public:
void setFunction(void *func);
void execFunction(T a, void *data);
};
template <class T> void FuncWrapper<T>::setFunction(void *func){
original_function = (void (*)(T))func;
}
template <class T> void FuncWrapper<T>::execFunction(T a, void *data){
FuncWrapper<T>* wrapper = (FuncWrapper<T>*)data;
std::cout << "inside wrapper " << *(a.get()) << std::endl;
wrapper->original_function(a);
}
main.cpp
#include <iostream>
#include <memory>
#include "header.h"
class ClassA{
public:
ClassA(std::shared_ptr<int> a){
FuncWrapper<std::shared_ptr<int>> *fw;
fw = new FuncWrapper<std::shared_ptr<int>>;
fw->setFunction((void*)&ClassA::print_int);
std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
g(a);
delete fw;
}
private:
void print_int(std::shared_ptr<int> x) {
std::cout << "printing int" << std::endl;
std::cout << "given int " << *(x.get()) << std::endl;
}
};
int main(int argc, char * argv[]){
std::shared_ptr<int> x = std::make_shared<int>(10);
std::cout << "inside main " << *(x.get()) << std::endl;
ClassA *temp;
temp = new ClassA(x);
delete temp;
return 0;
}
Result
inside main 10
inside wrapper 10
printing int
Segmentation fault (core dumped)
I cannot figure out why it causes segmentation fault.
Changing std::shared_ptr<int> to int works just fine.
Therefore I assume that it has to do with owenership of shared_ptr, but I'm not familiar with smart pointers and I'm completely at loss.
I want to know
why it does not work
how to make it work
Limitations are
w/o changing print_int function itself
execute function within FuncWrapper<T>::execFunction
FuncWrapper<T>::execFunction has to be static
Otherwise, it is free to change. (inside ClassA constructor, inside main execFunction etc.)
The problem is not the shared_ptr, but mismatch between pointers to a function and a member function.
Your function wrapper expects a pointer to a function (void (*)(std::shared_ptr<int>)), but you provide a pointer to a member function (void (ClassA::*)(std::shared_ptr<int>)), which is different. An implicit leading argument of pointer to this is added to it.
This is how it really looks like:
// pointer to member function
void (*)(ClassA *ptr, std::shared_ptr<int>)
Your shared_ptr goes to the first argument and fortunately the application segfaults.
One of the solutions is to make the function print_int static.
class ClassA{
public:
ClassA(std::shared_ptr<int> a){
FuncWrapper<std::shared_ptr<int>> *fw;
fw = new FuncWrapper<std::shared_ptr<int>>;
fw->setFunction((void*)&ClassA::print_int);
std::function<void(std::shared_ptr<int>)> g = std::bind(&FuncWrapper<std::shared_ptr<int>>::execFunction, fw, std::placeholders::_1, fw);
g(a);
delete fw;
}
private:
static void print_int(std::shared_ptr<int> x) {
std::cout << "printing int" << std::endl;
std::cout << "given int " << *(x.get()) << std::endl;
}
};
But there seems to be another problem in your code. Function pointers should not be converted to object pointers (which void * is). Maybe change your setFunction this way:
void setFunction(void (*func)(T)) {
original_function = func;
}
More on that here

error: no member function declared in class

I keep getting the following errors from my code:
(line 58) error: no 'std::string Person::Modify_Person(Person)' member function declared in class 'Person' In function 'int main()':
(line 113) error: 'Modify_Person' was not declared in this scope
Here is the code:
#include <iostream>
#include <string>
using namespace std;
void PassByByValue(int num2){
cout << "You are in PassByValue()" << endl;
num2++;
}
class Person{
int age;
string name;
int height;
int weight;
public:
Person(){
}
Person(string name){
this->name=name;
}
string getName(){
return this->name;
}
void setAge(int age){
this->age=age;
}
void setName(string name){
this->name=name;
}
void setHeight(int height){
this->height=height;
}
void setWeight(int weight){
this->weight=weight;
}
~Person(){
}
};
string Person::Modify_Person(Person example){
example.getName()="Jessica";
return example.getName();
}
void PassByRef(int& num3){
cout << "You are in PassByRef()" << endl;
num3=50;
cout << "inside PassByRef() pNum is: " <<num3<<endl;
}
int main()
{
int num1;
int* pNum;
num1=3;
*pNum=5;
PassByByValue(num1);
cout << "num1= " <<num1 <<endl;
PassByRef(*pNum);
cout << "outside PassByRef() in main() pNum is: " <<pNum<<endl;
PassByByValue(*pNum);
double* DblePtr;
DblePtr= new double;
*DblePtr=12.0;
cout<< "DblePtr: "<< &DblePtr;
delete[] DblePtr;
cout<< "DblePtr: "<< &DblePtr;
Person human;
human.setName("Kate");
human.setAge(27);
human.setHeight(100);
human.setWeight(100);
Modify_Person(human);
cout << "Modify_Person returns: " << Modify_Person(human) <<endl;
cout << "name should be Jessica: " << human.getName() << endl;
return 0;
}
You cannot declare a member function outside a class in C++. To fix this, add a corresponding member function declaration to your class:
class Person{
...
public:
string Modify_Person(Person);
};
Then your code will work. Also, a suggestion: don't define constructors and destructors if they are empty; allow the compiler to generate them for you. If you are intending to disable move constructors etc. by doing this, write Person() = default; to have the compiler generate a default implementation.
The function
string Person::Modify_Person(Person example) {
example.getName()="Jessica";
return example.getName();
}
has the following problems.
Use of string Person::Modify_Person(Person example) { ... } to define a function is valid only of Modify_Person is declared as a member function of the class. Since, it is not, you just need a global function.
string Modify_Person(Person example) {
...
}
The function cannot modify the object in the calling functions since the argument gets passed by value. No matter what you do to example, the value of the object that was used to call the function remains unchanged in the calling function. If you want to see any changes made to example to be visible in the calling function, you need to accept the argument by reference.
// |
// v
string Modify_Person(Person& example) {
...
}
The line
example.getName()="Jessica";
in the function does not modify the name of example. It is equivalent to saying:
string temp = example.getName();
temp = "Jessica";
Hence, the line below that returns the name of example will simply return the name of example, and not "Jessica", which I believe is counter to your expectation.
That line needs to be changed to:
example.setName("Jessica");
Here's what the function should look like:
string Modify_Person(Person& example) {
example.setName("Jessica");
return example.getName();
}

c++ passing function as argument to another function with void pointer

I'm trying to pass a function as argument to another function with void pointer and it doesn't work
#include <iostream>
using namespace std;
void print()
{
cout << "hello!" << endl;
}
void execute(void* f()) //receives the address of print
{
void (*john)(); // declares pointer to function
john = (void*) f; // assigns address of print to pointer, specifying print returns nothing
john(); // execute pointer
}
int main()
{
execute(&print); // function that sends the address of print
return 0;
}
The thing are the void function pointers, I could make an easier code like
#include <iostream>
using namespace std;
void print();
void execute(void());
int main()
{
execute(print); // sends address of print
return 0;
}
void print()
{
cout << "Hello!" << endl;
}
void execute(void f()) // receive address of print
{
f();
}
but I wonna know if I can use void pointers
it is for implement something like this
void print()
{
cout << "hello!" << endl;
}
void increase(int& a)
{
a++;
}
void execute(void *f) //receives the address of print
{
void (*john)(); // declares pointer to function
john = f; // assigns address of print to pointer
john(); // execute pointer
}
int main()
{
int a = 15;
execute(increase(a));
execute(&print); // function that sends the address of print
cout << a << endl;
return 0;
}
Using gcc test.cpp I get:
test.cpp: In function ‘void execute(void* (*)())’:
test.cpp:12:22: error: invalid conversion from ‘void*’ to ‘void (*)()’ [-fpermissive]
test.cpp: In function ‘int main()’:
test.cpp:18:19: error: invalid conversion from ‘void (*)()’ to ‘void* (*)()’ [-fpermissive]
test.cpp:9:6: error: initializing argument 1 of ‘void execute(void* (*)())’ [-fpermissive]
The signature for the f argument is incorrect. You need to use
void execute(void (* f)())
instead. Therefore, you don't need the cast when assigning to john:
john = f
Also, you can simplify this by calling f directly:
f(); // execute function pointer
EDIT: Since you want to use void pointers, you need to pass f as a void pointer:
void execute(void *f)
Here, you will need the assignment to john, but as f is already a void * you don't need the cast.
NOTE: Given that you are passing a void pointer, the execute function will accept anything and you will have runtime errors if you pass the wrong thing. For example:
void print_name(const char *name)
{
printf("%s", name);
}
void execute1(void *f);
void execute2(void (*f)());
int main()
{
int value = 2;
execute1(&value); // runtime crash
execute1(&print_name); // runtime crash
execute2(&value); // compile-time error
execute2(&print_name); // compile-time error
}
Using a specifically defined function pointer lets the compiler generate an error at the point where you have passed the wrong argument type. This is preferred to crashing at runtime, as the runtime crash may be exploited as a security vulnerability and requires extensive testing to ensure this error does not occur.
Use
void execute(void (*f)()) //receives the address of print
Or better use:
void execute(boost::function<void()> const & f) //receives the address of print
To accept functors as well, or replace boost:: with std:: if you are using compiler which supports C++11