Casting function pointers to and from void*

Discussion in 'C++' started by Peter Olcott, Jan 5, 2007.

  1. Peter Olcott

    Peter Olcott Guest

    I want to make a generic interface between a scripting language and native code,
    the native code and the interpreter will both be written in C++. The interpreter
    will probably be implemented as a subset of C/C++, thus will have the same
    syntax as C/C++.

    Somehow the interpreted code must be able to store generic function pointers
    because there is no way for the interpreter to know every possible function
    signature in advance. I was thinking about casting them to void* for this
    purpose.

    The interpreted function will be provided with the generic function pointer, and
    the function prototype as text. The interpreter will prepare the stack itself
    based on this function prototype. What I want to end up with is a simple
    interface for users of the interpreter that is identical to the interface for
    the native code users.

    In other words if the function prototype is:
    int FunctionName(int N);
    I want uses of my interpreter to be able to specify:
    int Result = FunctionName(56);
    when they are calling the native code functions.

    What kind of C++ syntax will be needed for this?
     
    Peter Olcott, Jan 5, 2007
    #1
    1. Advertising

  2. Peter Olcott

    Noah Roberts Guest

    Peter Olcott wrote:
    > I want to make a generic interface between a scripting language and native code,
    > the native code and the interpreter will both be written in C++. The interpreter
    > will probably be implemented as a subset of C/C++, thus will have the same
    > syntax as C/C++.
    >
    > Somehow the interpreted code must be able to store generic function pointers
    > because there is no way for the interpreter to know every possible function
    > signature in advance. I was thinking about casting them to void* for this
    > purpose.
    >
    > The interpreted function will be provided with the generic function pointer, and
    > the function prototype as text. The interpreter will prepare the stack itself
    > based on this function prototype. What I want to end up with is a simple
    > interface for users of the interpreter that is identical to the interface for
    > the native code users.
    >
    > In other words if the function prototype is:
    > int FunctionName(int N);
    > I want uses of my interpreter to be able to specify:
    > int Result = FunctionName(56);
    > when they are calling the native code functions.
    >
    > What kind of C++ syntax will be needed for this?


    I don't understand your problem as stated but maybe boost::function
    will aid you.
     
    Noah Roberts, Jan 5, 2007
    #2
    1. Advertising

  3. Peter Olcott

    Philipp Reh Guest

    On Fri, 05 Jan 2007 10:21:46 -0600, Peter Olcott wrote:

    > I want to make a generic interface between a scripting language and native code,
    > the native code and the interpreter will both be written in C++. The interpreter
    > will probably be implemented as a subset of C/C++, thus will have the same
    > syntax as C/C++.
    >
    > Somehow the interpreted code must be able to store generic function pointers
    > because there is no way for the interpreter to know every possible function
    > signature in advance. I was thinking about casting them to void* for this
    > purpose.
    >
    > The interpreted function will be provided with the generic function pointer, and
    > the function prototype as text. The interpreter will prepare the stack itself
    > based on this function prototype. What I want to end up with is a simple
    > interface for users of the interpreter that is identical to the interface for
    > the native code users.
    >
    > In other words if the function prototype is:
    > int FunctionName(int N);
    > I want uses of my interpreter to be able to specify:
    > int Result = FunctionName(56);
    > when they are calling the native code functions.
    >
    > What kind of C++ syntax will be needed for this?


    You can't cast a pointer to a function to a pointer to an object.
    reinterpret_cast can convert between two pointers to different functions
    only.
     
    Philipp Reh, Jan 5, 2007
    #3
  4. Peter Olcott

    Peter Olcott Guest

    "Philipp Reh" <> wrote in message
    news:459e9093$-siegen.de...
    > On Fri, 05 Jan 2007 10:21:46 -0600, Peter Olcott wrote:
    >
    >> I want to make a generic interface between a scripting language and native
    >> code,
    >> the native code and the interpreter will both be written in C++. The
    >> interpreter
    >> will probably be implemented as a subset of C/C++, thus will have the same
    >> syntax as C/C++.
    >>
    >> Somehow the interpreted code must be able to store generic function pointers
    >> because there is no way for the interpreter to know every possible function
    >> signature in advance. I was thinking about casting them to void* for this
    >> purpose.
    >>
    >> The interpreted function will be provided with the generic function pointer,
    >> and
    >> the function prototype as text. The interpreter will prepare the stack itself
    >> based on this function prototype. What I want to end up with is a simple
    >> interface for users of the interpreter that is identical to the interface for
    >> the native code users.
    >>
    >> In other words if the function prototype is:
    >> int FunctionName(int N);
    >> I want uses of my interpreter to be able to specify:
    >> int Result = FunctionName(56);
    >> when they are calling the native code functions.
    >>
    >> What kind of C++ syntax will be needed for this?

    >
    > You can't cast a pointer to a function to a pointer to an object.
    > reinterpret_cast can convert between two pointers to different functions
    > only.


    Is there any standard C++ way to accomplish what I need to accomplish?
     
    Peter Olcott, Jan 5, 2007
    #4
  5. Peter Olcott

    Peter Olcott Guest

    "Philipp Reh" <> wrote in message
    news:459e9093$-siegen.de...
    > On Fri, 05 Jan 2007 10:21:46 -0600, Peter Olcott wrote:
    >
    >> I want to make a generic interface between a scripting language and native
    >> code,
    >> the native code and the interpreter will both be written in C++. The
    >> interpreter
    >> will probably be implemented as a subset of C/C++, thus will have the same
    >> syntax as C/C++.
    >>
    >> Somehow the interpreted code must be able to store generic function pointers
    >> because there is no way for the interpreter to know every possible function
    >> signature in advance. I was thinking about casting them to void* for this
    >> purpose.
    >>
    >> The interpreted function will be provided with the generic function pointer,
    >> and
    >> the function prototype as text. The interpreter will prepare the stack itself
    >> based on this function prototype. What I want to end up with is a simple
    >> interface for users of the interpreter that is identical to the interface for
    >> the native code users.
    >>
    >> In other words if the function prototype is:
    >> int FunctionName(int N);
    >> I want uses of my interpreter to be able to specify:
    >> int Result = FunctionName(56);
    >> when they are calling the native code functions.
    >>
    >> What kind of C++ syntax will be needed for this?

    >
    > You can't cast a pointer to a function to a pointer to an object.
    > reinterpret_cast can convert between two pointers to different functions
    > only.


    void Test() {
    printf("Hello World!\n");
    }

    void (*pf)() = Test;

    void* vp = (void*) pf;

    This all compiles and executes correctly on my compiler.

    // All I need now is something like:
    goto *vp;
    // sets the instruction pointer to the address contain in vp.

    Is there anyway that anything like this can be done in standard C++ ???
     
    Peter Olcott, Jan 5, 2007
    #5
  6. Peter Olcott

    Marcus Kwok Guest

    Peter Olcott <> wrote:
    > void Test() {
    > printf("Hello World!\n");
    > }
    >
    > void (*pf)() = Test;
    >
    > void* vp = (void*) pf;
    >
    > This all compiles and executes correctly on my compiler.


    Even though it *seems* to work, it is not correct.

    http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.8

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
     
    Marcus Kwok, Jan 11, 2007
    #6
  7. Peter Olcott

    Peter Olcott Guest

    "Marcus Kwok" <> wrote in message
    news:eo61fo$4k4$...
    > Peter Olcott <> wrote:
    >> void Test() {
    >> printf("Hello World!\n");
    >> }
    >>
    >> void (*pf)() = Test;
    >>
    >> void* vp = (void*) pf;
    >>
    >> This all compiles and executes correctly on my compiler.

    >
    > Even though it *seems* to work, it is not correct.


    It indeed does work, I checked the generated assembly language. It only has to
    work on a single platform/compiler. When getting the job done requires breaking
    the rules, the rules must be broken.

    >
    > http://www.parashift.com/c -faq-lite/pointers-to-members.html#faq-33.8
    >
    > --
    > Marcus Kwok
    > Replace 'invalid' with 'net' to reply
     
    Peter Olcott, Jan 11, 2007
    #7
  8. Peter Olcott wrote:

    > When getting the job done requires breaking the rules, the rules must be
    > broken.


    Please don't blame the job when it's you who decide to break the rules.

    --
    Salu2
     
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Jan 11, 2007
    #8
  9. Peter Olcott

    Marcus Kwok Guest

    Peter Olcott <> wrote:
    >
    > "Marcus Kwok" <> wrote in message
    > news:eo61fo$4k4$...
    >> Peter Olcott <> wrote:
    >>> void Test() {
    >>> printf("Hello World!\n");
    >>> }
    >>>
    >>> void (*pf)() = Test;
    >>>
    >>> void* vp = (void*) pf;
    >>>
    >>> This all compiles and executes correctly on my compiler.

    >>
    >> Even though it *seems* to work, it is not correct.

    >
    > It indeed does work, I checked the generated assembly language. It only has to
    > work on a single platform/compiler. When getting the job done requires breaking
    > the rules, the rules must be broken.


    Sure, but then it is no longer Standard C++. Sorry, I don't have an
    answer to your real question. Maybe someone on a group for your
    platform or compiler will have a suggestion that is known to work for
    your situation.

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
     
    Marcus Kwok, Jan 11, 2007
    #9
  10. Peter Olcott

    Peter Olcott Guest

    "Julián Albo" <> wrote in message
    news:...
    > Peter Olcott wrote:
    >
    >> When getting the job done requires breaking the rules, the rules must be
    >> broken.

    >
    > Please don't blame the job when it's you who decide to break the rules.
    >
    > --
    > Salu2


    I don't have to get my system working in theory, I have to get it working in
    practice. If it does not work in theory yet does work in practice, then the
    theory is discarded.
     
    Peter Olcott, Jan 11, 2007
    #10
  11. Peter Olcott

    Peter Olcott Guest

    "Marcus Kwok" <> wrote in message
    news:eo67j5$66s$...
    > Peter Olcott <> wrote:
    >>
    >> "Marcus Kwok" <> wrote in message
    >> news:eo61fo$4k4$...
    >>> Peter Olcott <> wrote:
    >>>> void Test() {
    >>>> printf("Hello World!\n");
    >>>> }
    >>>>
    >>>> void (*pf)() = Test;
    >>>>
    >>>> void* vp = (void*) pf;
    >>>>
    >>>> This all compiles and executes correctly on my compiler.
    >>>
    >>> Even though it *seems* to work, it is not correct.

    >>
    >> It indeed does work, I checked the generated assembly language. It only has
    >> to
    >> work on a single platform/compiler. When getting the job done requires
    >> breaking
    >> the rules, the rules must be broken.

    >
    > Sure, but then it is no longer Standard C++. Sorry, I don't have an
    > answer to your real question. Maybe someone on a group for your
    > platform or compiler will have a suggestion that is known to work for
    > your situation.


    I was able to infer that casting to a specific function pointer type would not
    generally be possible. It would not generally be possible because the function
    pointer requires the compile time support of preparing the stack.

    >
    > --
    > Marcus Kwok
    > Replace 'invalid' with 'net' to reply
     
    Peter Olcott, Jan 11, 2007
    #11
  12. Peter Olcott

    Gavin Deane Guest

    Peter Olcott wrote:
    > I don't have to get my system working in theory, I have to get it working in
    > practice. If it does not work in theory yet does work in practice, then the
    > theory is discarded.


    The problem you create for yourself when you take this approach is that
    you have no way of knowing for how long your solution will continue to
    work in practice. Examining the generated assembly language is a valid
    way of checking that the behaviour in practice of your code is what you
    want when the behaviour in theory is formally undefined. However,
    unless your compiler documents the behaviour in practice as an
    extension (which it may well do), you have no way of knowing how stable
    the behaviour in practice is in the face of changes, such as compiler
    options, debug vs release build, or a change in the code itself. Your
    code is potentially very brittle. Every time you change something and
    recompile, you have to reexamine the generated assembly language to see
    if you still have the behaviour in practice that you need.

    Only you know how likely such changes and the associated need to
    recompile are, so only you are in a position to assess the relative
    costs of losing robustness in the code vs. redesigning to avoid the
    problem in the first place. But it is an assessment you must make.

    Gavin Deane
     
    Gavin Deane, Jan 12, 2007
    #12
  13. Peter Olcott

    Greg Guest

    Marcus Kwok wrote:
    > Peter Olcott <> wrote:
    > >
    > > "Marcus Kwok" <> wrote in message
    > > news:eo61fo$4k4$...
    > >> Peter Olcott <> wrote:
    > >>> void Test() {
    > >>> printf("Hello World!\n");
    > >>> }
    > >>>
    > >>> void (*pf)() = Test;
    > >>>
    > >>> void* vp = (void*) pf;
    > >>>
    > >>> This all compiles and executes correctly on my compiler.
    > >>
    > >> Even though it *seems* to work, it is not correct.

    > >
    > > It indeed does work, I checked the generated assembly language. It only has to
    > > work on a single platform/compiler. When getting the job done requires breaking
    > > the rules, the rules must be broken.

    >
    > Sure, but then it is no longer Standard C++. Sorry, I don't have an
    > answer to your real question. Maybe someone on a group for your
    > platform or compiler will have a suggestion that is known to work for
    > your situation.


    Function-to-object pointer conversions have been added to standard C++
    as a "conditionally supported" conversion using reinterpret_cast<>:

    "Converting a pointer to a function into a pointer to an object 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 an rvalue of one type to the
    other type and back, possibly with different cv-qualification, shall
    yield the original pointer value." [expr.reinterpret.cast/8]

    Conditionally-supported behavior is one that an implementation is not
    required to support. But an implementation does support the feature
    must then implement the feature as specified.

    Greg
     
    Greg, Jan 12, 2007
    #13
  14. Peter Olcott

    Pete Becker Guest

    Gavin Deane wrote:
    > Peter Olcott wrote:
    >> I don't have to get my system working in theory, I have to get it working in
    >> practice. If it does not work in theory yet does work in practice, then the
    >> theory is discarded.

    >
    > The problem you create for yourself when you take this approach is that
    > you have no way of knowing for how long your solution will continue to
    > work in practice. Examining the generated assembly language is a valid
    > way of checking that the behaviour in practice of your code is what you
    > want when the behaviour in theory is formally undefined. However,
    > unless your compiler documents the behaviour in practice as an
    > extension (which it may well do), you have no way of knowing how stable
    > the behaviour in practice is in the face of changes, such as compiler
    > options, debug vs release build, or a change in the code itself. Your
    > code is potentially very brittle. Every time you change something and
    > recompile, you have to reexamine the generated assembly language to see
    > if you still have the behaviour in practice that you need.
    >
    > Only you know how likely such changes and the associated need to
    > recompile are, so only you are in a position to assess the relative
    > costs of losing robustness in the code vs. redesigning to avoid the
    > problem in the first place. But it is an assessment you must make.
    >


    Despite all these dire threats, Unix programmers have been storing
    function pointers in void*'s for years. I'd even be so bold as to
    suggest that any compiler that didn't suppport this idiom on a Unix
    system where code and data pointers are the same size would be a
    failure. At the end of the day, it's more important to have code that
    works than to be hypothetically pure.

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, Jan 12, 2007
    #14
  15. Pete Becker wrote:

    > Despite all these dire threats, Unix programmers have been storing
    > function pointers in void*'s for years.


    An many unix or non unix programs have failed to work when compiled on
    different machines or compilers for decades. Maybe there are some
    correlation...

    --
    Salu2
     
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Jan 12, 2007
    #15
  16. Peter Olcott

    Marcus Kwok Guest

    Greg <> wrote:
    > Function-to-object pointer conversions have been added to standard C++
    > as a "conditionally supported" conversion using reinterpret_cast<>:
    >
    > "Converting a pointer to a function into a pointer to an object 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 an rvalue of one type to the
    > other type and back, possibly with different cv-qualification, shall
    > yield the original pointer value." [expr.reinterpret.cast/8]


    Interesting, thanks.

    > Conditionally-supported behavior is one that an implementation is not
    > required to support. But an implementation does support the feature
    > must then implement the feature as specified.


    Is there a consolidated list of other "conditionally-supported"
    features?

    --
    Marcus Kwok
    Replace 'invalid' with 'net' to reply
     
    Marcus Kwok, Jan 12, 2007
    #16
  17. Peter Olcott

    Pete Becker Guest

    Julián Albo wrote:
    > Pete Becker wrote:
    >
    >> Despite all these dire threats, Unix programmers have been storing
    >> function pointers in void*'s for years.

    >
    > An many unix or non unix programs have failed to work when compiled on
    > different machines or compilers for decades. Maybe there are some
    > correlation...
    >


    Sigh. More FUD.

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, Jan 12, 2007
    #17
  18. Peter Olcott

    Gavin Deane Guest

    Pete Becker wrote:
    > Gavin Deane wrote:
    > > Peter Olcott wrote:
    > >> I don't have to get my system working in theory, I have to get it working in
    > >> practice. If it does not work in theory yet does work in practice, then the
    > >> theory is discarded.

    > >
    > > The problem you create for yourself when you take this approach is that
    > > you have no way of knowing for how long your solution will continue to
    > > work in practice. Examining the generated assembly language is a valid
    > > way of checking that the behaviour in practice of your code is what you
    > > want when the behaviour in theory is formally undefined. However,
    > > unless your compiler documents the behaviour in practice as an
    > > extension (which it may well do), you have no way of knowing how stable
    > > the behaviour in practice is in the face of changes, such as compiler
    > > options, debug vs release build, or a change in the code itself. Your
    > > code is potentially very brittle. Every time you change something and
    > > recompile, you have to reexamine the generated assembly language to see
    > > if you still have the behaviour in practice that you need.
    > >
    > > Only you know how likely such changes and the associated need to
    > > recompile are, so only you are in a position to assess the relative
    > > costs of losing robustness in the code vs. redesigning to avoid the
    > > problem in the first place. But it is an assessment you must make.
    > >

    >
    > Despite all these dire threats, Unix programmers have been storing
    > function pointers in void*'s for years. I'd even be so bold as to
    > suggest that any compiler that didn't suppport this idiom on a Unix
    > system where code and data pointers are the same size would be a
    > failure. At the end of the day, it's more important to have code that
    > works than to be hypothetically pure.


    Clearly, code that doesn't work is no use. If such code is formally
    correct and, according to the standard should work, you have a QoI
    issue, unless your compiler documents its intended deviation from the
    standard.

    It is important that code works. Often (very often in my personal
    experience), it is also important that the code continues to work in
    the face of changes. Unless you have an inside line to the people who
    make your compiler, the language standard and your compiler's
    documentation of any omissions, extensions or variations from the
    language standard are your only means of knowing how the compiler
    manufacturer intends any C++ code to behave after their compiler has
    compiled it. If you step outside that, you're on your own, flying
    blind. As an engineer, stepping outside the manufacturer's
    specification should be a big decision.

    Gavin Deane
     
    Gavin Deane, Jan 12, 2007
    #18
  19. Peter Olcott

    Pete Becker Guest

    Gavin Deane wrote:
    > Pete Becker wrote:
    >> Gavin Deane wrote:
    >>> Peter Olcott wrote:
    >>>> I don't have to get my system working in theory, I have to get it working in
    >>>> practice. If it does not work in theory yet does work in practice, then the
    >>>> theory is discarded.
    >>> The problem you create for yourself when you take this approach is that
    >>> you have no way of knowing for how long your solution will continue to
    >>> work in practice. Examining the generated assembly language is a valid
    >>> way of checking that the behaviour in practice of your code is what you
    >>> want when the behaviour in theory is formally undefined. However,
    >>> unless your compiler documents the behaviour in practice as an
    >>> extension (which it may well do), you have no way of knowing how stable
    >>> the behaviour in practice is in the face of changes, such as compiler
    >>> options, debug vs release build, or a change in the code itself. Your
    >>> code is potentially very brittle. Every time you change something and
    >>> recompile, you have to reexamine the generated assembly language to see
    >>> if you still have the behaviour in practice that you need.
    >>>
    >>> Only you know how likely such changes and the associated need to
    >>> recompile are, so only you are in a position to assess the relative
    >>> costs of losing robustness in the code vs. redesigning to avoid the
    >>> problem in the first place. But it is an assessment you must make.
    >>>

    >> Despite all these dire threats, Unix programmers have been storing
    >> function pointers in void*'s for years. I'd even be so bold as to
    >> suggest that any compiler that didn't suppport this idiom on a Unix
    >> system where code and data pointers are the same size would be a
    >> failure. At the end of the day, it's more important to have code that
    >> works than to be hypothetically pure.

    >
    > Clearly, code that doesn't work is no use. If such code is formally
    > correct and, according to the standard should work, you have a QoI
    > issue, unless your compiler documents its intended deviation from the
    > standard.
    >
    > It is important that code works. Often (very often in my personal
    > experience), it is also important that the code continues to work in
    > the face of changes. Unless you have an inside line to the people who
    > make your compiler, the language standard and your compiler's
    > documentation of any omissions, extensions or variations from the
    > language standard are your only means of knowing how the compiler
    > manufacturer intends any C++ code to behave after their compiler has
    > compiled it. If you step outside that, you're on your own, flying
    > blind. As an engineer, stepping outside the manufacturer's
    > specification should be a big decision.
    >


    You're welcome to spend as much time as you like seeking purity. I'll
    trust Unix compilers to continue support standard idioms such as storing
    function addresses in void*'s, and I'll have robust, working code long
    before you do.

    --

    -- Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com)
    Author of "The Standard C++ Library Extensions: a Tutorial and
    Reference." (www.petebecker.com/tr1book)
     
    Pete Becker, Jan 12, 2007
    #19
  20. Pete Becker wrote:

    > You're welcome to spend as much time as you like seeking purity. I'll
    > trust Unix compilers to continue support standard idioms such as storing
    > function addresses in void*'s, and I'll have robust, working code long
    > before you do.


    Did you have? Looks like you are asking for advice because you haven't.

    --
    Salu2
     
    =?ISO-8859-15?Q?Juli=E1n?= Albo, Jan 12, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Ollej Reemt
    Replies:
    7
    Views:
    571
    Jack Klein
    Apr 22, 2005
  2. David M. Wilson
    Replies:
    8
    Views:
    500
    Ben Pfaff
    Jan 7, 2004
  3. Peter Goddard

    void pointers & void function pointers

    Peter Goddard, May 16, 2005, in forum: C Programming
    Replies:
    3
    Views:
    527
    Peter Goddard
    May 16, 2005
  4. Replies:
    5
    Views:
    852
    S.Tobias
    Jul 22, 2005
  5. Replies:
    1
    Views:
    423
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page