LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-31-2009, 01:05 PM   #1
gafferuk
LQ Newbie
 
Registered: Mar 2009
Posts: 18

Rep: Reputation: 0
Quick help with c++ callback


hi, how do i do a callback from one class to another?

heres my code, it does not compile parentClass saying: error: converting from ‘void (ParentClass::*)()’ to ‘void*’


Code:
// the function i wish to call
void ParentClass::process()
{
    // do something
}

ParentClass::ParentClass()
{
    childClass = new  ChildClass(process);
}
Code:
// childClass header file
class ChildClass
{
public:
    ChildClass(void (*processCallback)(void));

    void (*processCallback)(void);
}
Code:
// childClass source file
ChildClass::ChildClass(void (*processCallback)(void))
: processCallback(processCallback)
{
}
Thanks for your time.

Last edited by gafferuk; 03-31-2009 at 01:06 PM.
 
Old 03-31-2009, 02:47 PM   #2
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
I can't tell whether you want the callback to be a static member of the parent class or an ordinary member of the parent class.

If it is a static member, then you can initialize an ordinary pointer to function in the child class with the pointer to static function of the parent class, and no object of the parent class is used when calling the function from the child class.

If it is an ordinary member function of the parent class then you must store it as a member pointer (not an ordinary function pointer) and invoke it as a member pointer, using an object of the parent class.

Your decision on that choice affects the syntax for every step of the process, so I can't correct anything you did without that choice.

You have only shown some of the places in your code affected by that choice. I would expect to see:

The place in the parent class definition where you declare the callback function. Maybe also the place you define the callback function.

The place in the child class you declare the constructor that takes the function pointer as input. Maybe also the place you define that.

The place in the child class you declare the data member that holds the function pointer. Also the place you define that.

The place in the child class you invoke the function through that pointer.

BTW I assume your use of "parent" and "child" is conceptual for your application, not any formal OOP meaning (for example your child class is not derived from your parent class).

Last edited by johnsfine; 03-31-2009 at 02:54 PM.
 
Old 03-31-2009, 03:17 PM   #3
rjlee
Senior Member
 
Registered: Jul 2004
Distribution: Ubuntu 7.04
Posts: 1,994

Rep: Reputation: 76
I would tend to pass the actual object and just call a method on it, or an overloaded () operator.
 
Old 03-31-2009, 03:19 PM   #4
gafferuk
LQ Newbie
 
Registered: Mar 2009
Posts: 18

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by johnsfine View Post
I can't tell whether you want the callback to be a static member of the parent class or an ordinary member of the parent class.

If it is a static member, then you can initialize an ordinary pointer to function in the child class with the pointer to static function of the parent class, and no object of the parent class is used when calling the function from the child class.

If it is an ordinary member function of the parent class then you must store it as a member pointer (not an ordinary function pointer) and invoke it as a member pointer, using an object of the parent class.

Your decision on that choice affects the syntax for every step of the process, so I can't correct anything you did without that choice.

You have only shown some of the places in your code affected by that choice. I would expect to see:

The place in the parent class definition where you declare the callback function. Maybe also the place you define the callback function.

The place in the child class you declare the constructor that takes the function pointer as input. Maybe also the place you define that.

The place in the child class you declare the data member that holds the function pointer. Also the place you define that.

The place in the child class you invoke the function through that pointer.

BTW I assume your use of "parent" and "child" is conceptual for your application, not any formal OOP meaning (for example your child class is not derived from your parent class).
thanks for the info, im looking for an ordinary member function example and yes the client/parant names are just example names.
 
Old 03-31-2009, 03:42 PM   #5
gafferuk
LQ Newbie
 
Registered: Mar 2009
Posts: 18

Original Poster
Rep: Reputation: 0
heres a fuller example im after, please corrent my mistakes.

Code:
void main()
{
    ParentClass* parent = new ParentClass();
}
Code:
// parentClass header file
class ParentClass
{
public:
    ParentClass();

    ChildClass* childClass;
}

Code:
// parentClass source file
ParentClass::ParentClass()
{
    childClass = new  ChildClass(process);
}

// the function i wish to call
void ParentClass::process()
{
    // do something
}
Code:
// childClass header file
class ChildClass
{
public:
    ChildClass(void (*processCallback)(void));

    void (*processCallback)(void);
}
Code:
// childClass source file
ChildClass::ChildClass(void (*processCallback)(void))
: processCallback(processCallback)
{
}

void ChildClass::someFunction()
{
    ...
    // now i wish to call the parent class at some point
    processCallback();
}
Thanks.

Last edited by gafferuk; 03-31-2009 at 03:46 PM.
 
Old 03-31-2009, 03:50 PM   #6
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
You quoted everything I wrote, but I don't think you really read it.

Quote:
Originally Posted by johnsfine View Post
If it is an ordinary member function of the parent class then you must store it as a member pointer (not an ordinary function pointer) and invoke it as a member pointer, using an object of the parent class.
If it is an ordinary member function, there must be an object of that class used at the point the function is invoked.

Quote:
The place in the parent class definition where you declare the callback function.
You still showed just the definition, not the declaration.

That mainly matters if you were to realize you don't really want it to be an ordinary member function.

Code:
void ChildClass::someFunction()
{
    ...
    // now i wish to call the parent class at some point
    processCallback();
}
For which specific object of the parent class is it making that call?

Quote:
Originally Posted by rjlee View Post
I would tend to pass the actual object and just call a method on it
Without knowing the purpose of the callback, it is hard to guess the best approach.

A pointer to member function is needed in the complicated case that both the identity of the object and the identity of member function within the class vary. If either doesn't vary then some simpler approach would be better.

Many times a beginner asks a question like this, neither the object nor the member function actually varies. The parent is a "singleton" (a class for which only one object will ever exist) and the callback is just a form of information hiding (the child code shouldn't see the parent class definition). In that case, the clean approach is a parent static member to point to the singleton object combined with a parent static function for the callback that uses the static pointer to invoke the real function.

At the opposite extreme, there are cases where both the object and the member vary and you need the information hiding as well.

I think something like bind1st(mem_fun(&ParentClass::process),this)
can be used to create something that would act like an ordinary function pointer while actually binding a specific object ("this" in the context where that is invoked) with a specific member function.

I would expect to need a little experimentation and sorting out obscure compiler errors to use that myself. I don't know this part of C++ well enough to get every detail of that right on the first try.

Last edited by johnsfine; 03-31-2009 at 04:21 PM.
 
Old 03-31-2009, 04:14 PM   #7
gafferuk
LQ Newbie
 
Registered: Mar 2009
Posts: 18

Original Poster
Rep: Reputation: 0
It's simple what im after:

My main function creates a object called ParentClass.
this ParentClass creates a object called childClass.
At some point in time i wish for child class to call a function in the parent class, a simple callback.

Also, it's to be used in a dynamic shared library(the class I called childClass) if that makes any difference?

Thanks you.

Last edited by gafferuk; 03-31-2009 at 04:19 PM.
 
Old 03-31-2009, 04:28 PM   #8
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by gafferuk View Post
At some point in time i wish for child class to call a function in the parent class, a simple callback.
Do you understand the difference between a class and an object?

In describing what you want to do, you seem to be ignoring that difference.

You cannot simply call a member function "in a class". You must call a member function for a specific object.

If at the time you store the address of the member function, you want to bind it together with the identity of the object, you need something like what I was editing onto the end of my previous post while you typed the above.

If you want to decide the object seperately from storing the pointer to member function, then you need to have the object known to the caller of the member function.
 
Old 03-31-2009, 04:42 PM   #9
gafferuk
LQ Newbie
 
Registered: Mar 2009
Posts: 18

Original Poster
Rep: Reputation: 0
a class is an object.

i just want one class to create another class and that class at some point to call one of the first first classes methods.

this is getting all silly, im no beginner, just have not created a callback in linux, im from the windows world.

heres a link to my last project i created but am now rebuilding it for linux. : http://forum.ableton.com/viewtopic.p...1817&start=150
 
Old 03-31-2009, 04:56 PM   #10
gafferuk
LQ Newbie
 
Registered: Mar 2009
Posts: 18

Original Poster
Rep: Reputation: 0
i wish to create a dynamic shared library. how do i get this shared library to call a function in the class that open the library?
 
Old 03-31-2009, 05:02 PM   #11
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
Quote:
Originally Posted by gafferuk View Post
a class is an object.
this is getting all silly, im no beginner, just have not created a callback in linux, im from the windows world.
This is not a platform issue it is a language issue. It seems after much trying on johnsfine's behalf you are failing to understand the intricacies of member functions. I would recommend reading this part of the parashift C++ faqs if you would like to understand it. On the other hand if you do not want to reinvent the wheel, personally I think reinventing it in this instance is good for learning, then you could use boost function or it's underlying classstraight away.
These are not the only methods of doing what you wish, as pointed out you can use std::mem_func or many libraries which provide you with functionality such as this or this

Last edited by dmail; 03-31-2009 at 05:09 PM. Reason: added links to fast delegates, loki and std::mem_func
 
Old 03-31-2009, 05:13 PM   #12
gafferuk
LQ Newbie
 
Registered: Mar 2009
Posts: 18

Original Poster
Rep: Reputation: 0
Quote:
Originally Posted by dmail View Post
This is not a platform issue it is a language issue.
There is no difference, windows and linux both use c++ but use a different api for loading shared libries.

Is there any one here with experiance in creating shared libries on linux and then calling a function/method/procedure in the class that opened the library. Or in other words, pass an event back to the host.

Last edited by gafferuk; 03-31-2009 at 05:17 PM.
 
Old 03-31-2009, 05:27 PM   #13
raconteur
Member
 
Registered: Dec 2007
Location: Slightly left of center
Distribution: slackware
Posts: 276
Blog Entries: 2

Rep: Reputation: 44
johnsfine hit the nail squarely: "A pointer to member function is needed in the complicated case that both the identity of the object and the identity of member function within the class vary. If either doesn't vary then some simpler approach would be better."

You wrote:

Quote:
Originally Posted by gafferuk View Post
[...]i just want one class to create another class and that class at some point to call one of the first first classes methods.[...]
And then:

Quote:
Originally Posted by gafferuk View Post
i wish to create a dynamic shared library. how do i get this shared library to call a function in the class that open the library?
Those are very different statements...

In the first case, the simplest approach would be to pass a pointer to the parent class in the constructor of the child class, or any one of half a dozen similar methods of referring to a parent class. That isn't a callback.

In the second statement, you really are talking about a callback.

You will need to define a function in your library that includes a parameter for a user-defined function (basic callback stuff, the same as in Windows). That function should be global or at least a static member function in the calling application.
 
Old 03-31-2009, 05:34 PM   #14
dmail
Member
 
Registered: Oct 2005
Posts: 970

Rep: Reputation: Disabled
Quote:
Originally Posted by gafferuk View Post
There is no difference, windows and linux both use c++ but use a different api for loading shared libries.
Yes dynamic libraries are a platform issue, but you claimed the platform was relevant to a functor or at least that was the way I interpreted it.
Quote:
Is there any one here with experiance in creating shared libries on linux and then calling a function/method/procedure in the class that opened the library. Or in other words, pass an event back to the host.
Yes this is exactly what the following piece of code does in a dynamic library:
Code:
	Generic_keyboard::Generic_keyboard(LVD::Window* window):m_window(window)
	{
		Window_event e;
		e.type = Window_event::KEY_PRESS;
		m_window->register_handler(Window::Event_handler(this,&Generic_keyboard::keychange ),e);
Where the generic keyboard inherits from a abstract base class which declares the virtual function keychange and is implemented in the dynamic library class Generic_keyboard.

Did you read the links which I posted as they have the information which you require. If you read them you will see that the information required in not really suitable for a forum posting it is instead more article worthy.

If you have any problems after reading and trying to implement it, then just post back and I will be more than happy to help.
 
Old 03-31-2009, 05:50 PM   #15
gafferuk
LQ Newbie
 
Registered: Mar 2009
Posts: 18

Original Poster
Rep: Reputation: 0
umm im just looking for a simple answer to my question, shared libries, how to pass an event back to the host with the minimum of fuss. any ideas?
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
what are callback functions ? rbh123 Linux - Newbie 1 01-04-2007 11:14 AM
A problem about callback scanner Programming 6 07-05-2006 03:40 AM
Problem with Callback! Linuxnewbie Linux - Networking 1 02-24-2004 01:55 AM
ISDN + callback zeky Linux - General 0 12-25-2002 07:15 AM
Dailup callback Bogdan Linux - Newbie 0 12-21-2001 02:56 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 05:49 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration