[iostreams][tru64] can't pass static mem fn to API expecting extern "C"

Hi, Compaq C++ for Tru64 seems to have found a problem with the iostreams library that none of the other compilers caught. zlib and libbz2 allow the programmer to customize memory management by specifying a pair of function pointers for allocation and deallocation. I wanted to provide an adaption layer so that users could specify standard library compatible allocators instead. To do this, I defined a class template parameterized by an allocator and having two static member functions with the same signature as the allocation and deallocation functions, and then passed pointers to these static member functions to the zlib and libbz2 API. Unfortunately, when compiled as C++, the zlib and libbz2 headers declare the allocation and deallocation function pointer types as extern "C", and Compaq (correctly, I think) refuses to let me assign pointers to static member functions to variables whose type are declared extern "C". Is there some way to get around this? If not, what should I do? 1. expose the C-language customization interface (yuck) 2. remove the customization interface 3. remove the customization interface only for platforms where it doesn't work 4. Use some more elaborate trick, such as supplying extern "C" allocation functions which operate by delegating to pointers stored in a table. I like 2. Jonathan

From: "Jonathan Turkanis" <technews@kangaroologic.com>
Compaq C++ for Tru64 seems to have found a problem with the iostreams library that none of the other compilers caught.
zlib and libbz2 allow the programmer to customize memory management by specifying a pair of function pointers for allocation and deallocation. I wanted to provide an adaption layer so that users could specify standard library compatible allocators instead. To do this, I defined a class template parameterized by an allocator and having two static member functions with the same signature as the allocation and deallocation functions, and then passed pointers to these static member functions to the zlib and libbz2 API.
Unfortunately, when compiled as C++, the zlib and libbz2 headers declare the allocation and deallocation function pointer types as extern "C", and Compaq (correctly, I think) refuses to let me assign pointers to static member functions to variables whose type are declared extern "C".
The static member functions have C++ language linkage, not C language linkage, so Tru64 is correct.
Is there some way to get around this?
If not, what should I do?
1. expose the C-language customization interface (yuck) 2. remove the customization interface 3. remove the customization interface only for platforms where it doesn't work 4. Use some more elaborate trick, such as supplying extern "C" allocation functions which operate by delegating to pointers stored in a table.
The first question to address is whether the customization is needed. zlib and libbz2 obviously provide the customization for a reason, but is that necessary in your library? Assuming the customization is needed, a mechanism such as 4 is appropriate. You hide the extern "C" details in your library, but provide clients with a means to affect the allocation. If you design things such that use of the adaptation layer sets up and registers the extern "C" functions, but otherwise doesn't supply customization functions to zlib or libbz2, then 2 is a degenerate form of 4 (when no one uses the adaptation layer). Thus, 2 would be a good starting point, with 4 added later should a library client require it. -- Rob Stewart stewart@sig.com Software Engineer http://www.sig.com Susquehanna International Group, LLP using std::disclaimer;

Rob Stewart wrote:
From: "Jonathan Turkanis"
Unfortunately, when compiled as C++, the zlib and libbz2 headers declare the allocation and deallocation function pointer types as extern "C", and Compaq (correctly, I think) refuses to let me assign pointers to static member functions to variables whose type are declared extern "C".
The static member functions have C++ language linkage, not C language linkage, so Tru64 is correct.
... what should I do?
1. expose the C-language customization interface (yuck) 2. remove the customization interface 3. remove the customization interface only for platforms where it doesn't work 4. Use some more elaborate trick, such as supplying extern "C" allocation functions which operate by delegating to pointers stored in a table.
The first question to address is whether the customization is needed. zlib and libbz2 obviously provide the customization for a reason, but is that necessary in your library?
My eventual goal is to have all use of dynamically allocated memory customizable by library users.
Assuming the customization is needed, a mechanism such as 4 is appropriate. You hide the extern "C" details in your library, but provide clients with a means to affect the allocation.
It's potentially pretty messy, though, especially w.r.t thread safety.
If you design things such that use of the adaptation layer sets up and registers the extern "C" functions, but otherwise doesn't supply customization functions to zlib or libbz2, then 2 is a degenerate form of 4 (when no one uses the adaptation layer).
If I'm not going to allow users to customize memory allocation, there's no reason to register any extern "C" functions, since zlib and libbz2 provide reasonable defaults (presumably using malloc/free).
Thus, 2 would be a good starting point, with 4 added later should a library client require it.
I guess this is what I'll do for now. Thanks for your input. Jonathan

Rob Stewart <stewart@sig.com> writes:
From: "Jonathan Turkanis" <technews@kangaroologic.com>
[snip]
Unfortunately, when compiled as C++, the zlib and libbz2 headers declare the allocation and deallocation function pointer types as extern "C", and Compaq (correctly, I think) refuses to let me assign pointers to static member functions to variables whose type are declared extern "C".
The static member functions have C++ language linkage, not C language linkage, so Tru64 is correct.
It seems to me that it is the calling convention that matters, not the linkage/name mangling. I don't see what extern "C" applied to a function pointer type means. This restriction does not seem right to me. [snip] -- Jeremy Maitin-Shepard

Jeremy Maitin-Shepard wrote:
Rob Stewart <stewart@sig.com> writes:
From: "Jonathan Turkanis" <technews@kangaroologic.com>
[snip]
Unfortunately, when compiled as C++, the zlib and libbz2 headers declare the allocation and deallocation function pointer types as extern "C", and Compaq (correctly, I think) refuses to let me assign pointers to static member functions to variables whose type are declared extern "C".
The static member functions have C++ language linkage, not C language linkage, so Tru64 is correct.
It seems to me that it is the calling convention that matters, not the linkage/name mangling. I don't see what extern "C" applied to a function pointer type means. This restriction does not seem right to me.
It means a pointer to an extern "C" function. When you call it, the extern "C" calling convention is used.
participants (4)
-
Jeremy Maitin-Shepard
-
Jonathan Turkanis
-
Peter Dimov
-
Rob Stewart