TITLE: a sharp angle on function pointers [This is a slightly abridged version of Glen McCluskey's C++ Newsletter. See the contact/subscription info at the trailer for more information. -adc] Issue #028 October, 1997 Contents: Introduction to C++ Libraries Part 1 - and Notes From ANSI/ISO - A Sharp Angle On Function Pointers Introduction to Object-oriented Design Part 7 - More About Extensibility INTRODUCTION TO C++ LIBRARIES PART 1 - AND [snip] NOTES FROM ANSI/ISO - A SHARP ANGLE ON FUNCTION POINTERS Jonathan Schilling, jls@sco.com At the summer 1996 ANSI/ISO standards meeting, the concept of language linkage was extended to cover pointer to function types, such that there are now pointers to C functions and pointers to C++ functions as distinct types. This change was described in C++ Newsletter issue #021, "A New Angle on Function Pointers". Now that this feature is being introduced into compilers, such as SCO's new C++ compiler, we are seeing how it can break existing code. Consider first this usage: something.h: extern "C" { void f(int); } something.C: #include "something.h" void f(int) { ... } where both header and source file are compiled with C++ (that is, this is a C++ function that you want to be callable from C as well). The definition in the source file does not have extern "C" on it, but because it is the same f(int) as in the declaration in the header, the language rules state that the extern "C" from the declaration applies to it as well. The definition for f is thus generated with C linkage, that is, with the unmangled name "f". Now suppose we do the same thing, but with a pointer to function as a parameter: something.h: extern "C" { void g(int (*pf)()); } something.C: #include "something.h" void g(int (*pf)()) { ... } Under the old language rules, the definition of g would get its language linkage from the declaration of g, and thus would be generated with C linkage and the unmangled name "g", just as in the case above. But under the new language rule, g is generated with C++ linkage and a mangled name such as "g__FPFv_i", and a link-time error will likely result. Why does this happen? Because now the language linkage applies not only to the function it is specified for, but also to any other names or declarators introduced by the declaration of that function. In this case this means the linkage applies to the pointer-to-function pf. So the declaration of g is within an extern "C" block, which means that its pf is considered a pointer to a C function. However the definition of g is not within an extern "C" block, which means that its pf is considered a pointer to a C++ function. Thus the parameters are of different types, thus the two g's are considered different and overloaded rather than the same function, thus the extern "C" on the first g does not extend to the second, and thus g is generated with C++ linkage and a mangled name. There are two ways the code can be revised to work properly. The first is to put the definition into an extern "C" block as well: something.C: extern "C" { void g(int (*pf)()) { ... } } This works because the definition's pf will now also be interpreted as a pointer to C function, and so the two g's are the same. The second approach is to use a typedef for the pointer to function: something.h: extern "C" { typedef int (*pf)(); void g(pf); } something.C: void g(pf) { ... } This works because the typedef preserves the "pointer to C" characteristic of the type when pf appears again in the definition of g. Either of these approaches will also work properly with compilers implementing the old language rules. INTRODUCTION TO OBJECT-ORIENTED DESIGN PART 7 - MORE ABOUT EXTENSIBILITY [snip] ACKNOWLEDGEMENTS Thanks to Nathan Myers, Eric Nagler, David Nelson, and Jonathan Schilling for help with proofreading. SUBSCRIPTION INFORMATION / BACK ISSUES To subscribe to the newsletter, send mail to majordomo@world.std.com with this line as its message body: subscribe c_plus_plus Back issues are available via FTP from: ftp.glenmccl.com /morespace1/glenmccl/newslett or on the Web at: http://www.glenmccl.com/~glenm There is also a Java newsletter. To subscribe to it, say: subscribe java_letter using the same majordomo@world.std.com address. ------------------------- Copyright (c) 1997 Glen McCluskey. All Rights Reserved. This newsletter may be further distributed provided that it is copied in its entirety, including the newsletter number at the top and the copyright and contact information at the bottom. Glen McCluskey & Associates Professional C++ Consulting Internet: glenm@glenmccl.com Phone: (800) 722-1613 or (970) 490-2462 Fax: (970) 490-2463 FTP: ftp.glenmccl.com /morespace1/glenmccl/newslett (for back issues) Web: http://www.glenmccl.com/~glenm