C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Casting function pointer to different signature - compiler c

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
jeffz_2002@yahoo.com
Guest





PostPosted: Sun Jun 26, 2005 2:08 pm    Post subject: Casting function pointer to different signature - compiler c Reply with quote



/*
Hello,

To implement a C++ simulation I was working on, I started looking at
Vladimir Batov's code from CUJ, Feb 2001 ("Callbacks Made Easy with the
Observer-Mediator Design Patterns"). Most of the code is
straightforward, but I can't follow the central mechanism behind his
design that lets it work. I've boiled the problem down to the code
below -- specifically the function doSomethingVoidPtr, where casting a
function pointer's signature to a different signature lets the code
bypass the compiler's type checking of function arguments. The console
output follows the code.


As shown in line A, the function pointer doSomething gets cast to a
different signature. In line B, this function pointer is then called
with an address to an A, which has previously been cast to a void *.
Somehow, though I'm not sure how, the program manages to take this
address-of-an-A-as-ptr-to-void and convert it to a const A& argument,
as required by doSomething. Question: How and why does it do this? I
assumed that C++'s compiler would balk at this, but it compiled.

Some extra notes:
- I had to cast the whole function's signature to an f_t, I couldn't
just call doSomething with a void *.
- when I call this function pointer with a void * which contains an
address to a B (line C), the program gives garbage. It seems the code
is casting the void* to A's bit pattern (terminology?), and so trying
to get x_ from the non-A object gives crap (or will
crash program).

Thanks,

Jeff


P.S.: For the curious, the point in question in Batov's code is in the
method Parcel::call, where the function pointer member_callback_ is
given an event and a pointer-to-void sender. member_callback_ is then
cast to a different signature [typedef void (Callee::*MemberCallback)
(const Event&, void*)], when the Parcel object is created ... see the
macro #FAMILY in signals.h. Unfortunately, the article doesn't really
go into the casting of the of function pointer to different types,
which is unfortunate, since it's the trick that allows his pattern to
work.


*/


#include <iostream>
using namespace std;

struct A {
A(int x) : x_(x) {};
int x_;
};

struct B {};

void doSomething(const A& a) {
cout << "doSomething: " << a.x_ << endl;
}

void doSomethingVoidPtr(void* a) {
typedef void (*f_t)(void *);

// line A - casting doSomething to different signature.
f_t myFun = (f_t)doSomething;

// line B - calling the function, passing in a void* arg.
(*myFun)(a);
}



int main() {
A a(42);
cout << "Calling with an A: ";
doSomething(a);

void* p = &a;
// doSomething(p); // doesn't compile.
cout << "Calling with a void* pointing at an A: ";
doSomethingVoidPtr(p);

B b;
void* vb = &b;
cout << "Calling with a void* pointing at a B: ";
doSomethingVoidPtr(vb); // line C

return 0;
}


/* Output:
Calling with an A: doSomething: 42
Calling with a void* pointing at an A: doSomething: 42
Calling with a void* pointing at a B: doSomething: 586179681
*/

/* FYI:
$ g++ --version
g++ (GCC) 3.3.1 (cygming special)

Thanks! Jeff
*/


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
jeffz_2002@yahoo.com
Guest





PostPosted: Mon Jun 27, 2005 10:43 am    Post subject: Re: Casting function pointer to different signature - compil Reply with quote



// Hi folks, I just realized I could simplify the code for my question:

#include <iostream>
using namespace std;

struct A {
A(int x) : x_(x) {};
int x_;
};


struct B {};


void doSomething(const A& a) { cout << "doSomething: " << a.x_ << endl;
}



int main() {
A a(42);
B b;

typedef void (*void_func_void_ptr_arg)(void *);

void_func_void_ptr_arg f = (void_func_void_ptr_arg)doSomething; //
line A

void* vpa = &a;
(*f)(vpa); // line B ... prints "doSomething: 42"

void* vpb = &b;
(*f)(vpb); // line C ... prints "doSomething: 1089" (garbage)

return 0;
}

// Thanks, Jeff


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Jack Klein
Guest





PostPosted: Tue Jun 28, 2005 9:57 am    Post subject: Re: Casting function pointer to different signature - compil Reply with quote



On 27 Jun 2005 06:43:16 -0400, [email]jeffz_2002 (AT) yahoo (DOT) com[/email] wrote in
comp.lang.c++.moderated:

Quote:
// Hi folks, I just realized I could simplify the code for my question:

#include using namespace std;

struct A {
A(int x) : x_(x) {};
int x_;
};


struct B {};


void doSomething(const A& a) { cout << "doSomething: " << a.x_ << endl;
}



int main() {
A a(42);
B b;

typedef void (*void_func_void_ptr_arg)(void *);

void_func_void_ptr_arg f = (void_func_void_ptr_arg)doSomething; //
line A

void* vpa = &a;
(*f)(vpa); // line B ... prints "doSomething: 42"

void* vpb = &b;
(*f)(vpb); // line C ... prints "doSomething: 1089" (garbage)

return 0;
}

// Thanks, Jeff

The compiler does not cast anything at all. What you doing is
inducing undefined behavior. A pointer is not a reference and a
reference is not a pointer. You are making a call to a function and
passing an argument of a type different than that accepted by the
function. Anything that does or does not happen is not specified by
the C++ language and might just happen to be an artifact of the way
your compiler passes pointers and references.

The code just happens to work, or not work, as you observe, on your
particular implementation. From the C++ language point of view, it is
just plain undefined.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.