473,804 Members | 3,396 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

C2664 and passing member function pointer

9 New Member
I am attempting to use a wrapper class to the Win32 timer API in a Visual C++ 6.0 MFC application. The callback function needs to have access to the front panel, and as such needs to be a member of the front panel class. I kept getting compile error C2276 when I tried passing the address of a member function. After implementing a few changes suggested by the author of the class, I now get the following error when compiling:

error C2664: 'setCallbackFun ction' : cannot convert parameter 1 from 'void (__stdcall CTestDlg::*)(in t)' to 'void (__cdecl *)(int)'
There is no context in which this conversion is possible

The line that causes the error is:
Expand|Select|Wrap|Line Numbers
  1. timer1.setCallbackFunction(&CTestDlg::timer1Event);
The prototype of the callback function looks like this:
Expand|Select|Wrap|Line Numbers
  1. void CALLBACK CTestDlg::timer1Event(int i)
The prototype of the setCallbackFunc tion function looks like this:
Expand|Select|Wrap|Line Numbers
  1. VOID LRTimer::setCallbackFunction( VOID (*_pCallback)(int)) {
  2.         m_pCallback = _pCallback;
  3. }
Do you have any ideas as to how I might fix this? I would greatly appreciate it if I could get a fix within the next 48 hours - this is a rather important part of a project I'm working on. I tried contacting the author of the class, but it looks like he hasn't been active for a while.

Thank you!
Ian
Sep 9 '07 #1
3 4425
Banfa
9,065 Recognized Expert Moderator Expert
Expand|Select|Wrap|Line Numbers
  1. VOID LRTimer::setCallbackFunction( VOID (*_pCallback)(int)) {
  2.         m_pCallback = _pCallback;
  3. }
This function takes a pointer to a function, not a pointer to a function member of an object. That is internally setCallbackFunc tion (and LRTIMER) has no knowledge of the any object containing the callback function and does not perform any of the pointer manipulation (creating and passing this) that would be required to call a object member function. And in fact dopes not have access to the data required to create this.

Expand|Select|Wrap|Line Numbers
  1. void CALLBACK CTestDlg::timer1Event(int i)
This function is a member of CTestDlg and before calling requires that this is created and passed to timer1Event.

Solutions

You could make CTestDlg::timer 1Event a static function. This means that timer1Event is a class method, it would be unable to access any object data through this as the this pointer is not set up for class methods. Obviously only you can say if you are able to work with this constraint. May be the data passed would be enough for you t identify the object required and then call a normal method on the object from the class member function.

You could change the prototype of setCallbackFunc tion if you have access to all it's source code (i.e. you are not using it as a library. In this case you change setCallbackFunc tion (or add an overload of it) and all the relevent places in the LRTimer class to accept a pointer to and object of type CTestDlg. And then internally call the relevent member function.

Expand|Select|Wrap|Line Numbers
  1. VOID LRTimer::setCallbackFunction( CTestDlg *pCallbackObject)
Sep 10 '07 #2
ifitzgerald
9 New Member
Expand|Select|Wrap|Line Numbers
  1. VOID LRTimer::setCallbackFunction( VOID (*_pCallback)(int)) {
  2.         m_pCallback = _pCallback;
  3. }
This function takes a pointer to a function, not a pointer to a function member of an object. That is internally setCallbackFunc tion (and LRTIMER) has no knowledge of the any object containing the callback function and does not perform any of the pointer manipulation (creating and passing this) that would be required to call a object member function. And in fact dopes not have access to the data required to create this.

Expand|Select|Wrap|Line Numbers
  1. void CALLBACK CTestDlg::timer1Event(int i)
This function is a member of CTestDlg and before calling requires that this is created and passed to timer1Event.

Solutions

You could make CTestDlg::timer 1Event a static function. This means that timer1Event is a class method, it would be unable to access any object data through this as the this pointer is not set up for class methods. Obviously only you can say if you are able to work with this constraint. May be the data passed would be enough for you t identify the object required and then call a normal method on the object from the class member function.

You could change the prototype of setCallbackFunc tion if you have access to all it's source code (i.e. you are not using it as a library. In this case you change setCallbackFunc tion (or add an overload of it) and all the relevent places in the LRTimer class to accept a pointer to and object of type CTestDlg. And then internally call the relevent member function.

Expand|Select|Wrap|Line Numbers
  1. VOID LRTimer::setCallbackFunction( CTestDlg *pCallbackObject)
Banfa, thank you very much for your quick response. Unfortunately my automatic notification settings must be incorrect, and I didn't notice your response until this morning.

What I ended up doing was creating a non-member function to use as the callback, and calling member functions in the callback using a global pointer to "this".

Expand|Select|Wrap|Line Numbers
  1. VOID timer1Event()
  2. {
  3.      dialogObject->memberFunction(); //dialogObject is a pointer to the form object
  4. }
  5.  
I know global variables aren't exactly the best programming practice, but eventually I'll need several different timers each with a different callback function, and this was the easiest way that I could think of to do it.

Thanks again,
Ian
Sep 12 '07 #3
Banfa
9,065 Recognized Expert Moderator Expert
Banfa, thank you very much for your quick response. Unfortunately my automatic notification settings must be incorrect, and I didn't notice your response until this morning.
The automatic notification on this site is somewhat broken, I suggest you check back to the site itself every now and then and check your user control panel for updates.

What I ended up doing was creating a non-member function to use as the callback, and calling member functions in the callback using a global pointer to "this".

Expand|Select|Wrap|Line Numbers
  1. VOID timer1Event()
  2. {
  3.      dialogObject->memberFunction(); //dialogObject is a pointer to the form object
  4. }
  5.  
I know global variables aren't exactly the best programming practice, but eventually I'll need several different timers each with a different callback function, and this was the easiest way that I could think of to do it.
OK, that is definately the quick and dirty hack :D and you have the prototype of timer1Event wrong, it is supposed to accept an int parameter. This hack will not scale.

Here is what I would say is a better solution

You need a way to associate the LRTimer instance with the CTestDlg instance. Do you access to the code of both classes?

If so then pass a pointer to your CTestDlg instance to the LRTimer, the callback can then be a member function of CTestDlg which LRTimer can call directly, but you would have to handle the case of the CTestDlg instance being deleted before the LRTimer instance had timed out (i.e. the risk of LRTimer trying to use an invalid CTestDlg instance).

If you do not have access to both classes, particularly access to the LRTimer class then:

Firstly make the callback a static member of CTestDlg, if possible make it private. This will only be possible if you create the timer from within the CTestDlg class somewhere.

To associate the 2 instances you will need to have identifying data, this could be the pointer to the class or it could be an id, whatever it is it must uniquely identify the instance. You can then set up a map (again a private member of CTestDlg) which you will be able to consult to get the correct CTestDlg instance for any LRTimer callback and so call the correct object.

When instances are deleted you can simple remove the corresponding map member to prevent use of invalid pointers.
Sep 13 '07 #4

Sign in to post your reply or Sign up for a free account.

Similar topics

5
9380
by: Newsgroup - Ann | last post by:
Gurus, I have the following implementation of a member function: class A { // ... virtual double func(double v); void caller(int i, int j, double (* callee)(double)); void foo() {caller(1, 2, func);
7
1557
by: James Vanns | last post by:
Sounds nasty doesn't it!! Well it's kinda what I need to do! I have an external C struct (external to the C++ project/classes etc.) which is wants a function ptr assigned to one of it's members: struct blah { int (func_ptr*) (int a, int b, float c); }; etc... However, my code is in C++ and a wish to assign a non-static member function (I know I can do this) to this struct member! Can this be
6
8832
by: keepyourstupidspam | last post by:
Hi, I want to pass a function pointer that is a class member. This is the fn I want to pass the function pointer into: int Scheduler::Add(const unsigned long timeout, void* pFunction, void* pParam)
17
2815
by: Christopher Benson-Manica | last post by:
Does the following program exhibit undefined behavior? Specifically, does passing a struct by value cause undefined behavior if that struct has as a member a pointer that has been passed to free()? #include <stdlib.h> struct stype { int *foo; };
11
4435
by: cps | last post by:
Hi, I'm a C programmer taking my first steps into the world of C++. I'm currently developing a C++ 3D graphics application using GLUT (OpenGL Utility Toolkit written in C) for the GUI components. The application is built around a "World" object that contains a "GUI" object that is a C++ wrapper around GLUT. What I'd like to do is pass a pointer to a member function in the World class to function in the GUI
3
2625
by: dice | last post by:
Hi, In order to use an external api call that requires a function pointer I am currently creating static wrappers to call my objects functions. I want to re-jig this so I only need 1 static wrapper function. I would prefer to be able to pass the member function as a void* to the static wrapper but I suspect this may not even be possible. Another solution would be option 2 below but I can't figure out the syntax to call obj->*pFn(). ...
7
3310
by: TS | last post by:
I was under the assumption that if you pass an object as a param to a method and inside that method this object is changed, the object will stay changed when returned from the method because the object is a reference type? my code is not proving that. I have a web project i created from a web service that is my object: public class ExcelService : SoapHttpClientProtocol {
18
2884
by: tbringley | last post by:
I am a c++ newbie, so please excuse the ignorance of this question. I am interested in a way of having a class call a general member function of another class. Specifically, I am trying to write an ordinary differential equation class that would solve a general equation in the form: dx/dt = f(x,t). The ode class shouldn't know anything about f, except how to call it.
8
3508
by: S. | last post by:
Hi all, Can someone please help me with this? I have the following struct: typedef struct { char *name; int age; } Student;
0
9705
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9575
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
1
10308
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9134
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6846
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5645
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4288
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3806
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2981
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.