I cannot figure the syntax to declare a function pointer as a static member.
#include <iostream>
using namespace std;
class A
{
static void (*cb)(int a, char c);
};
void A::*cb = NULL;
int main()
{
}
g++ outputs the error "cannot declare pointer to `void' member". I assume I need to do something with parentheses but void A::(*cb) = NULL does not work either.
I introduced a typedef, which made it somewhat clearer in my opinion:
class A
{
typedef void (*FPTR)(int a, char c);
static FPTR cb;
};
A::FPTR A::cb = NULL;
void (*A::cb)(int a, char c) = NULL;
Related
I am creating a C++ library from a C library.
C library have functions that contain callback,and callback have also arg(number of arguments).
I want to expose callback class override functions to the user so that the user can access callback function data.
As shown in this example user use callback class
To simplify, I created the smallest version of my issue.
Here I am trying to use a standard C function with a callback and assign a pure virtual function as the callback.
/// library.h part of code //////
#include <iostream>
extern "C" {
#include<stdio.h>
}
extern "C" {
void qsort(void *base, size_t nmemb, size_t size, int (*)(const void *, const void *));
}
struct callback{
virtual int compare(const void *a, const void *b)=0;
};
struct myclass{
myclass()=default;
callback *callback_;
void mycallback(callback& cb){
callback_ = &cb;
}
void sortdata(int *array,int size){
qsort((void*)array,size,sizeof(int),callback::compare);
//qsort((void*)array,size,sizeof(int),&callback_->compare);
};
};
and
////Application.cpp part code ///////////////////
//#include "library.h"
class usercallback : public callback{
public:
//currenty only one callback but in my case many
virtual int compare(const void *a, const void *b) override{
std::cout<<__PRETTY_FUNCTION__<<std::endl;
return *((int*)a) < *((int*)b);
}
};
int main(){
int array[] = {1,2,4,5,7,8,93,2,4,6,7,89,43,2,4,5};
int size = sizeof(array)/sizeof(array[0]);
myclass myobj;
usercallback cb;
myobj.mycallback(cb);
myobj.sortdata(array,size);
}
this program gives error and i gauss because of C++ internally pass this object as arg.
error: invalid use of non-static member function ‘virtual int callback::compare(const void*, const void*)’
23 | qsort((void*)array,size,sizeof(int),callback::compare);
I have also read this article.but it not solve my problem.
i also know that it can be solved by using static, but i want to expose a class to the users, as in this example.
code building on Ubuntu.
The ideal solution is to not paint yourself in that corner in the first place. If you have any leeway at all towards addressing this differently from a design standpoint, that should be your goto.
That being said, if you are stuck, and HAVE to make that interoperability work, you'll have to marhsall the this available from a free-floating function, which means a global variable. A private static member variable is the best approach for this here, and ideally, it should be thread_local for safety.
For example:
// library.h
struct myclass{
myclass()=default;
void mycallback(callback& cb){
callback_ = &cb;
}
void sortdata(int *array,int size){
active_instance_ = this;
qsort((void*)array,size,sizeof(int),compare_entry);
active_instance_ = nullptr;
};
private:
callback *callback_;
static thread_local myclass* active_instance_;
static int compare_entry(const void *a, const void *b) {
assert(active_instance_);
active_instance_->callback_->compare(a, b);
}
};
// library.cpp
thread_local myclass* myclass::active_instance_ = nullptr;
Obviously, this is only fine for callbacks that only live until the stack unwinds. It is inappropriate for anything involving long-lived callbacks.
For those, hopefully, the API in question provides a void* user_data pointer in which you can store this. If so, then you would be able to do:
//assuming
void register_callback(void* user_data, void (*cb)(void*, int));
// library.h
struct myclass{
myclass()=default;
void mycallback(callback& cb){
callback_ = &cb;
register_callback(this, callback_entry);
}
private:
callback *callback_;
static int callback_entry(void* user_data, int p) {
auto self = reinterpret_cast<myclass*>(user_data);
self->callback_->some_method(p);
}
};
I am trying to call pointer to a void * function inside the main method and the compiler is saying assigning to 'funcptr<g>' from incompatible type 'void *(void *). hello function is actually an argument to pthread_create function. That's why it is void * function. How can I create a function pointer to a void * function?
#include <iostream>
#include <pthread.h>
using namespace std;
template<typename T>
using funcptr = void (*T::*)(void *); // I think it is wrong here.
class m {
public:
template <typename T>
struct my_struct {
funcptr<T> ptr;
};
};
class g {
public:
static void *hello(void *);
};
int main() {
struct m::my_struct<g> h;
h.ptr = g::hello; // Error here
return 0;
}
How can I create a function pointer to a void * function?
hello is not a member function, but it's a static function.
So your funcptr should be as follows:
// No template needed.
using funcptr = void* (*)(void *)
Note that hello is declared with static, meaning that it's no longer a member function to g.
Static members of a class are not associated with the objects of the class.
So using void (*T::*)(void *) to cull non-member functions is incorrect.
If you're allowed to use a compiler that supports C++11, you don't even need to manually deduct its type anymore, using decltype:
// decltype deducts its exact type for you.
using funcptr = decltype(&g::hello);
class m
{
public:
struct my_struct
{
funcptr ptr;
};
};
FYI, since hello does not have its definition, you might encounter a linkage error. To prevent that, I assumed that there's some implementation inside:
static void *hello(void *)
{
// Meaningless, but..
return nullptr;
}
if you're using C++11, you can use std::function<> which just bothers about the return type and parameters of the function and not where they are defined and what are its type.
Here is the code using std::function<>
#include <iostream>
#include <functional>
#include <pthread.h>
using namespace std;
class m {
public:
template <typename T>
struct my_struct {
function<void*(void*)> ptr;
};
};
class g {
public:
static void *hello(void *) {
cout<<"Hello.."<<endl;
}
};
int main() {
struct m::my_struct<g> h;
h.ptr = g::hello;
h.ptr(nullptr);
return 0;
}
I don't understand pointers and references very well yet, but I have a class with static methods and variables that will be referenced from main and other classes. I have a variable defined in main() that I want to pass to a variable in this class with static functions. I want those functions to change the value of the variable that is seen in the main() scope.
This is an example of what I am trying to do, but I get compiler errors...
class foo
{
public:
static int *myPtr;
bool somfunction() {
*myPtr = 1;
return true;
}
};
int main()
{
int flag = 0;
foo::myPtr = &flag;
return 0;
}
Provide the definition of the static variable outside the class as:
//foo.h
class foo
{
public:
static int *myPtr; //its just a declaration, not a definition!
bool somfunction() {
*myPtr = 1;
//where is return statement?
}
}; //<------------- you also forgot the semicolon
/////////////////////////////////////////////////////////////////
//foo.cpp
#include "foo.h" //must include this!
int *foo::myPtr; //its a definition
Beside that, you also forgot the semicolon as indicated in the comment above, and somefunction needs to return a bool value.
#include <iostream>
using namespace std;
class foo
{
public:
static int *myPtr;
bool somfunction() {
*myPtr = 1;
return true;
}
};
//////////////////////////////////////////////////
int* foo::myPtr=new int(5); //You forgot to initialize a static data member
//////////////////////////////////////////////////
int main()
{
int flag = 0;
foo::myPtr = &flag;
return 0;
}
#include "stdafx.h"
class Person;
typedef void (Person::*PPMF)();
// error C2159: more than one storage class specified
typedef static void (Person::*PPMF2)();
class Person
{
public:
static PPMF verificationFUnction()
{
return &Person::verifyAddress;
}
// error C2440: 'return' : cannot convert from
// 'void (__cdecl *)(void)' to 'PPMF2'
PPMF2 verificationFUnction2()
{
return &Person::verifyAddress2;
}
private:
void verifyAddress() {}
static void verifyAddress2() {}
};
int _tmain(int argc, _TCHAR* argv[])
{
Person scott;
PPMF pmf = scott.verificationFUnction();
(scott.*pmf)();
return 0;
}
Question: I need to define a function pointer PPMF2 to pointing to a static member function verifyAddress2. How can I do it?
#include "stdafx.h"
class Person;
typedef void (Person::*PPMF)();
typedef void (Person::*PPMF2)();
class Person
{
public:
static PPMF verificationFUnction()
{
return &Person::verifyAddress;
}
PPMF2 verificationFUnction2()
{
return &Person::verifyAddress2;
}
private:
void verifyAddress() {}
static void verifyAddress2() {}
};
int _tmain(int argc, _TCHAR* argv[])
{
Person scott;
PPMF pmf = scott.verificationFUnction();
(scott.*pmf)();
return 0;
}
A pointer to a static member function is just a normal function pointer. typedef void (*PPMF2)(). You assign it to a static member function like you assign any function pointer, only that the static member function is inside the class scope:
PPMF2 myfunc = &MyClass::StaticMemberFunc;
About static member function guarantees:
С++ ISO/IEC 14882 2003-10-15 says that
5.2.2 There are two kinds of function call: ordinary function call and member function 57) (9.3) call....
57) A static member function (9.4) is an ordinary function.
Theoretically static-member-functions can have another calling convention.
But standart allow us to leverage on such thing...
Answer:
typedef void (Person::*PPMF2)() => typedef void (*PPMF2)()
If the function is static it does not require a (implicit) this pointer to be invoked. Therefore, a pointer to a static member function is not the same as a member function pointer:
#include "stdafx.h"
class Person;
typedef void (Person::*PPMF)();
typedef /*static*/ void (*PPMF2)();
class Person
{
public:
static PPMF verificationFUnction()
{
return &Person::verifyAddress;
}
PPMF2 verificationFUnction2()
{
return &Person::verifyAddress2;
}
private:
void verifyAddress() {}
static void verifyAddress2() {}
};
int _tmain(int argc, _TCHAR* argv[])
{
Person scott;
PPMF pmf = scott.verificationFUnction();
(*pmf)();
return 0;
}
EDIT:
removed the offending static from the typedef.
#include<iostream>
using namespace std;
class A
{
private:
int x,y;
static int a;
public:
A()
{
x = 10;
y = 11;
}
~A()
{
}
void displayNonStatic()
{
cout<<x<<" "<<y<<endl;
}
void displayStatic()
{
cout<<a<<endl;
}
};
int A::a = 12;
int main()
{
typedef void (A::*NonStatic)(void);
typedef void (A::*Static)(void);
A a1;
NonStatic _nstatic = &A::displayNonStatic ;
Static _static = &A::displayStatic;
// Always make sure that call to the pointer to the member functions is made within the context of the instance.
//Correct way to call the pointer within the context of the instance " a1 " .
(a1.*_nstatic)();
(a1.*_static)();
//Error case given below, the pointer is not called within the context of the instance
// (*_nstatic)(); ->error
// (*_static)(); ->error
getchar();
}
Refer to the link for more information.
I have a C library function that expects a function pointer for callback, and I want to pass in a C++ member function. The C++ function modifies a member variable, so I can't use a static free function (as suggested in several similar posts). My attempt (shown below) fails with a compiler error.
This post comes closest to what I need:
Using a C++ class member function as a C callback function
How can I do this without static functions? Thanks!
test.h
#ifndef TEST_H_
#define TEST_H_
#ifdef __cplusplus
extern "C" {
#endif
typedef void (*handler_t)(int foo, void *bar);
void set_handler(handler_t h);
#ifdef __cplusplus
}
#endif
#endif
test.c
#include "test.h"
#include <stdlib.h>
static handler_t handler_ = NULL;
void set_handler(handler_t h) {
handler_ = h;
}
void handle_event(int foo, void *bar) {
if (handler_ != NULL) handler_(foo, bar);
}
test.cpp
#include "test.h"
#include <iostream>
using namespace std;
class Foo {
public:
Foo() : ctr_(0) {};
// handler needs to access non-static variable, so it can't be static
void handler(int foo, void *bar) { ++ctr_; }
private:
int ctr_;
};
int main(int argc, char **argv) {
// error: can't convert to "void (*)(int, void*)"
set_handler(&Foo::handler);
cout << "done" << endl;
return 0;
}
GCC barf
$ gcc test.cpp test.c
test.cpp: In function ‘int main(int, char**)’:
test.cpp:18: error: cannot convert ‘void (Foo::*)(int, void*)’ to ‘void (*)(int, void*)’ for argument ‘1’ to ‘void set_handler(void (*)(int, void*))’
It is not possible, at least with that handler_t signature.
While you can create a free function on your .cpp to wrap the member call, you need a pointer to the Foo instance:
void my_wrap(int foo, void* bar) {
Foo* some_foo_instance = ...;
some_foo_instance->handler(foo, bar);
}
int main(int argc, char **argv) {
set_handler(&my_wrap);
}
You need some void* to pass the Foo instance as a handler attribute:
// Header
typedef void (*handler_t)(int foo, void *bar, void* arg1);
void set_handler(handler_t h, void* arg1);
// Impl.
void set_handler(handler_t h, void* arg1) {
handler_ = h;
handler_arg1_ = arg1;
}
// cpp
void my_wrap(int foo, void* bar, void* arg1) {
Foo* some_foo_instance = static_cast<Foo*>(arg1);
some_foo_instance->handler(foo, bar);
}
// main
int main(int argc, char **argv) {
Foo some_concrete_instance;
set_handler(&my_wrap, static_cast<void*>(&some_concrete_instance));
}
The big question is how many times you need to call set_handler multiple times to call methods on different objects. If this answer is one, you can do something like this:
#include <boost/function.hpp>
class HandlerContext
{
static boost::function<void (int, void*)> s_func
static void forward(int foo, void* bar)
{
s_func(foo, bar);
}
public:
static void set(boost::function<int, void*> const& f)
{
s_func = f;
set_handler(&HandlerContext::forward);
}
};
If the answer is "more than once", you can have multiple forwarding functions that get their function objects out of an array. You will need to preassign slots in this case, because the function in use will indicate which callback to make.
This sentence:
I have a C library function
This means you can NOT pass it any C++ object.
If the library you are using is a C library it does not know about C++ so it can not using anything that is C++ it can only use C stuff.
You MUST make it call a free function in you code.
Now your free function can then call a method on an object (that is why C callbacks have a void* parameter (so you can pass context to the callback)).
Suppose you create a mapping function:
Foo *inst = // some instance of Foo you're keeping around...
void wrapper(int foo, void *bar){
inst->handler(foo, bar);
}
Then use wrapper as the callback. Instance semantics in a callback are kind of strange, so I'm not sure how you're going to be sure you bind to the correct instance -- if this is a singleton maybe that doesn't matter.
Here is an ugly hack I invented awhile ago to solve this problem:
#include <boost/function.hpp>
#include <boost/bind.hpp>
using ::boost::function;
using ::boost::bind;
typedef int (*callback_t)(const char *, int);
typedef function<int(const char *, int)> MyFTWFunction;
template <MyFTWFunction *callback>
class callback_binder {
public:
static int callbackThunk(const char *s, int i) {
return (*callback)(s, i);
}
};
extern void register_callback(callback_t f);
int random_func(const char *s, int i)
{
if (s && *s) {
return i;
} else {
return -1;
}
}
MyFTWFunction myfunc;
class FooClass {
public:
virtual int callme(const char *s, int x) { return 0; };
};
int main(int argc, const char *argv[])
{
FooClass foo;
myfunc = bind(&FooClass::callme, &foo, _1, _2);
register_callback(&callback_binder<&myfunc>::callbackThunk);
return 0;
}
This could probably be fixed to use stuff from TR1 and remove the dependency on Boost.
And also, of course, myfunc is a global variable. It has to be a global variable. You must have one global variable per different possible object you'd want to call back into. OTOH, you can have as many of these globals as you want.
The main issue here is that it is absolutely impossible to do what you want within the given constraints. The pointer to the object you want to call back into has to come from somewhere. In some languages (like Python for example) you can create a function on-the-fly that has it's own copy of the object pointer. This cannot be done in C++. All functions must exist completely at compile time. You cannot create new function instances at run time.
With C++0x, you can sort of create functions at runtime with lambda functions. But these functions have an unspecified type and there is absolutely no way you could ever then pass them to a C function and have it work. Lambda expressions are meant to be supplied as template parameters and it's pretty hard to use them for anything else because their address can't be taken, and even if it could you ccouldn't actually know what type the pointer is pointing to.
I highly recommend not using it. The little void * most callback interfaces allow you to specify that gets handed back to you along with the data is meant to hold an object pointer of some kind. If possible, you should be doing that instead.
If you have control over how handler is defined, I recommend using Boost function objects instead of function pointers.
If you HAVE to use function pointers, define handler_t with an extra void* whose value is passed along with the handler, watch out for the gotchas Martin York linked in a comment. Then you have something like this:
typedef void (*handler_t)(int foo, void *bar, void *data);
static handler_t handler_ = NULL;
static void* handler_data_ = NULL;
void set_handler(handler_t h, void *d = NULL) {
handler_ = h;
handler_data = d;
}
void handle_event(int foo, void *bar) {
if (handler_ != NULL) handler_(foo, bar, handler_data_);
}
void foo_handler(int foo, void *bar, void *data) {
Foo *fooObj = static_cast<Foo*>(data);
fooObj->handler(foo, bar);
}
// in main
set_handler(foo_handler, &some_foo_object);