Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Casting function pointers into data and back

54 views
Skip to first unread message

Ghost

unread,
Jun 23, 2016, 1:05:50 PM6/23/16
to
HI there,

I find myself in a situation where I can only pass around
structs with no pointer members. However, I would like to
include information about function pointers. Is it possible
to cast a function pointer into some primitive type and
back in a safe and portable way? If I use reinterpret_cast,
is the success of the operation only a matter of the new
type being large enough?

If it is of any help, I'm trying to use the standardized
Fortran mechanism to mix Fortran and C, but I can only
have Fortran /derived types/ be mapped into C structs
if no pointer members are involved. Also, Fortran doesn't
define /interoperability/ between Fortran and C++, so I
also mix C++ and C using extern "C". Another limitation is
that Fortran doesn't have unsigned types.

Any help appreciated.
Thanks.

Victor Bazarov

unread,
Jun 23, 2016, 1:38:47 PM6/23/16
to
On 6/23/2016 1:05 PM, Ghost wrote:
> I find myself in a situation where I can only pass around
> structs with no pointer members. However, I would like to
> include information about function pointers. Is it possible
> to cast a function pointer into some primitive type and
> back in a safe and portable way? If I use reinterpret_cast,
> is the success of the operation only a matter of the new
> type being large enough?
>
> [..]

Yes, all correct, if your implementation provides an integral type large
enough to accommodate a pointer (to function, to object), you can use
'reinterpret_cast' to do the casting forth and back between a pointer
and that integral type. There is no standard type, it's all
implementation-specific ([expr.reinterpret.cast]/4 and /5).

V
--
I do not respond to top-posted replies, please don't ask

Ben Bacarisse

unread,
Jun 23, 2016, 2:53:12 PM6/23/16
to
Ghost <n...@spam.net> writes:

> I find myself in a situation where I can only pass around
> structs with no pointer members. However, I would like to
> include information about function pointers. Is it possible
> to cast a function pointer into some primitive type and
> back in a safe and portable way?

I don't think you can do it with a cast in a 100% portable way. You can
include cstdint and test for UINTPTR_MAX which will tell you if there is
a type uintptr_t type that can hold a pointer value (or, alternatively,
INTPTR_MAX for the signed version) but even that is only guaranteed to
work for object pointers.

The only portable method would be to copy the representation:

typedef void (*function_ptr)();
unsigned char fptr_rep[sizeof (function_ptr)];
...
function_ptr fp = ...;
memcpy(fptr_rep, &fp, sizeof fp);

but that, of course, is clumsy.

<snip>
--
Ben.

Alf P. Steinbach

unread,
Jun 23, 2016, 3:15:04 PM6/23/16
to
On 23.06.2016 20:53, Ben Bacarisse wrote:
> Ghost <n...@spam.net> writes:
>
>> I find myself in a situation where I can only pass around
>> structs with no pointer members. However, I would like to
>> include information about function pointers. Is it possible
>> to cast a function pointer into some primitive type and
>> back in a safe and portable way?
>
> I don't think you can do it with a cast in a 100% portable way. You can
> include cstdint and test for UINTPTR_MAX which will tell you if there is
> a type uintptr_t type that can hold a pointer value (or, alternatively,
> INTPTR_MAX for the signed version) but even that is only guaranteed to
> work for object pointers.

Since C++11 an implementation can support casting function pointer to
void* and back. Essentially because the Posix API requires that. And
then uintptr_t is necessarily large enough.

C++11 §5.2.10/8:
«Converting a function pointer to an object pointer type or vice versa
is conditionally-supported. The meaning of such a conversion is
implementation-defined, except that if an implementation supports
conversions in both directions, converting a prvalue of one type to the
other type and back, possibly with different cv-qualification, shall
yield the original pointer value.»



> The only portable method would be to copy the representation:
>
> typedef void (*function_ptr)();
> unsigned char fptr_rep[sizeof (function_ptr)];
> ...
> function_ptr fp = ...;
> memcpy(fptr_rep, &fp, sizeof fp);
>
> but that, of course, is clumsy.

Yep.

But I'd go for the portable-enough uintptr_t. ;-)


Cheers!,

- Alf

Richard

unread,
Jun 23, 2016, 3:32:57 PM6/23/16
to
[Please do not mail me a copy of your followup]

Ghost <n...@spam.net> spake the secret code
<nkh4t3$g7v$1...@dont-email.me> thusly:

>[...] Is it possible
>to cast a function pointer into some primitive type and
>back in a safe and portable way?

Not really

<http://stackoverflow.com/questions/12358843/why-are-function-pointers-and-data-pointers-incompatible-in-c-c>
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>

Ben Bacarisse

unread,
Jun 23, 2016, 4:14:00 PM6/23/16
to
"Alf P. Steinbach" <alf.p.stein...@gmail.com> writes:

> On 23.06.2016 20:53, Ben Bacarisse wrote:
>> Ghost <n...@spam.net> writes:
>>
>>> I find myself in a situation where I can only pass around
>>> structs with no pointer members. However, I would like to
>>> include information about function pointers. Is it possible
>>> to cast a function pointer into some primitive type and
>>> back in a safe and portable way?
>>
>> I don't think you can do it with a cast in a 100% portable way. You can
>> include cstdint and test for UINTPTR_MAX which will tell you if there is
>> a type uintptr_t type that can hold a pointer value (or, alternatively,
>> INTPTR_MAX for the signed version) but even that is only guaranteed to
>> work for object pointers.
>
> Since C++11 an implementation can support casting function pointer to
> void* and back. Essentially because the Posix API requires that. And
> then uintptr_t is necessarily large enough.

Yes, I wasn't very clear at all. I should have pointed out that
converting to uintptr_t only works for void * (I think C++ defers to C
on this matter) so you can't ever convert a function pointer directly.
(in the standard sense that is -- it is, of course, very likely to work
in practice). Thus two things are needed: the uintptr_t type and the
(two-way) conversion between function pointers and object pointers.

> C++11 §5.2.10/8:

Thanks for the quote. I didn't know this happened so late!

<snip>
>> The only portable method would be to copy the representation:
<snip>
> But I'd go for the portable-enough uintptr_t. ;-)

Sure, me too, but the OP's request was so odd (why no function pointers
in the structures?) that they may be looking at some very odd hardware
that really can't do it any other way.

--
Ben.

Scott Lurndal

unread,
Jun 23, 2016, 4:19:14 PM6/23/16
to
He's sharing the structure between fortran and C, and fortran
creates the C-structure definition used based on the COMMON
data being shared.

Ghost

unread,
Jun 24, 2016, 7:57:32 AM6/24/16
to
Thank you for all the answers.

Ghost

unread,
Jun 24, 2016, 7:59:20 AM6/24/16
to
I actually liked the idea.
Thanks.

> <snip>
>

Ghost

unread,
Jun 28, 2016, 9:25:34 AM6/28/16
to
Em 23/06/2016 14:05, Ghost escreveu:
I should mention that doing this wasn't necessary after all. The
Fortran standard, through its /iso_c_binding/ module, has this
situation covered by means of things like c_ptr and c_funptr.


0 new messages