Function Pointers in C not compiling with g++

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • saptarshi
    New Member
    • Apr 2007
    • 3

    #1

    Function Pointers in C not compiling with g++

    Hi
    I have header file in C (which cannot be changed).

    GraphicsDevice. h
    Code:
    ---some code---
    Rboolean (*open)();
    ---code continues
    Now another code(which also compiles in C) assigns to open like this
    dev->open = NULL_Open;

    where NULL_Open is defined as
    Code:
    static Rboolean NULL_Open(NewDevDesc *dev) {
        return TRUE;
    }
    I get the error when compiled with g++
    Code:
    error: invalid conversion from 'Rboolean (*)(NewDevDesc*)' to 'Rboolean (*)()
    How can I make g++ ignore this error? Or better, how do i fix it?
    Note, I can't change the header file code i.e
    Rboolean (*open)();
    must stay. Also, i would like NULL_Open to be defined as above (i.e taking a parameter)

    Thank you
    Saptarshi
  • mvbrevern
    New Member
    • Apr 2007
    • 5

    #2
    Originally posted by saptarshi
    Hi
    I have header file in C (which cannot be changed).

    GraphicsDevice. h
    Code:
    ---some code---
    Rboolean (*open)();
    ---code continues
    Now another code(which also compiles in C) assigns to open like this
    dev->open = NULL_Open;

    where NULL_Open is defined as
    Code:
    static Rboolean NULL_Open(NewDevDesc *dev) {
        return TRUE;
    }
    I get the error when compiled with g++
    Code:
    error: invalid conversion from 'Rboolean (*)(NewDevDesc*)' to 'Rboolean (*)()
    How can I make g++ ignore this error? Or better, how do i fix it?
    Note, I can't change the header file code i.e
    Rboolean (*open)();
    must stay. Also, i would like NULL_Open to be defined as above (i.e taking a parameter)

    Thank you
    Saptarshi
    The error is not be ignored. If you would ignore it the program would crash.

    We are dealing with function pointers. The attribute "open" of the object
    "dev" is of type "function returning Rboolean* and taking no argument".
    You pass a function returning Rboolean* but taking one argument
    (NewDevDesc*).

    If you would cast the function taking one argument to a function taking
    no argument (I better omitt the code here :)) the compiler would not complain.
    But later on when you run the program the dev->open attribute comes into
    play and the function it points to is called. But, no actual argument is passed
    along with it (the stack does not contain anything). Your function thinks an
    argument is passed, pops it from the stack and *bang* -> stack underflow.

    Comment

    • weaknessforcats
      Recognized Expert Expert
      • Mar 2007
      • 9214

      #3
      This code:
      Code:
      ---some code---
      Rboolean (*open)();
      ---code continues
      Declares a function pointer variable named "open" as a pointer to a functtion containing no arguments and returning an Rboolean.

      You may assign any function address to this pointer PROVIDED the function takes no arguments an Rboolean.

      You cannot assign the address of any other function to this and any type casting to get it to compile will just cause a crash when you run the program.

      The compiler inists on this becuse your function call using the pointer looks like:
      Code:
                 Rboolean rval = open();
      and for this to work the function pointer better contain the address of a function that has no argiments and returns an Rboolean.

      Comment

      • saptarshi
        New Member
        • Apr 2007
        • 3

        #4
        Thank you for the replies. I understand the predicament involved in expecting arguments but getting none (because of the declaration and definition contrasts)
        But then how does this compile and run in C?
        I can say this, because it is part of the R source code (The R Project - a statistical software - the code is in src/library/grDevices/src/devNull.c)
        and it works!

        I wanted to use QT, so i need to compile with g++

        Thank you.
        Saptarshi

        Comment

        • saptarshi
          New Member
          • Apr 2007
          • 3

          #5
          Hmm, i'm guessing that when the NULL_open is called, it is always called with an argument, though were it to be called with nothing it would crash.
          Anyways, assuming it is called with one argument, could you please show me how to recast the function to one that does not take any arguments? ? I ask because I'm learning C++ on this project itself.

          Thank you
          Saptarshi

          Comment

          • weaknessforcats
            Recognized Expert Expert
            • Mar 2007
            • 9214

            #6
            Originally posted by saptarshi
            Thank you for the replies. I understand the predicament involved in expecting arguments but getting none (because of the declaration and definition contrasts)
            But then how does this compile and run in C?
            I believe this is due to a difference between C and C++. In C:
            Code:
            Rboolean open();
            just identifies open as a function. The arguments are based on how the function is called the first time. In C++, however, this means a function that takes no arguments and returns an RBoolean. C++ is not C.

            Comment

            • AdrianH
              Recognized Expert Top Contributor
              • Feb 2007
              • 1251

              #7
              Weaknessforcats is partially correct, though it has nothing to do with how the function is first called. In C, if you do not specify any parameters, it is equivalent to declaring with an ellipsis. In C++, if you do not specify any parameters, it is equivalent to declaring with void.

              Code:
              /* in C these are equivalent */
              void fn();
              void fn(...);
              
              /* in C++ these are equivalent */
              void fn();
              void fn(void);
              If you are to declare a function in C without parameters or using the ellipsis[*], it is legal to define the function with any set of parameters you want. So the following is valid, if not dangerous:
              Code:
              /* in C the following is valid in header file */
              void fn();
              /* with the source file defining it like this */
              void fn(int foo, float bar)
              {
                /* do stuff */
              }
              It is dangerous because you could do a call to fn() with anything, an int and a float as is required, or just a double or even nothing at all. As you can see, the problem with doing this is that if the function is not passed the correct arguments, the compiler will allow it with no warnings. This is REALLY BAD.

              There could be some legitimate reason to do this, but I’m tired and can’t think of one at the moment. However, you may be able to allow for this behaviour. To do this, you would need to use the extern "C" { ... } syntax. This would be best done in the header file like this:
              Code:
              #if defined __cplusplus
              extern "C" {
              #endif
              
              // C prototypes here
              
              #if defined __cplusplus
              }
              #endif
              If you do not have access to modifying the header file you can try the following, I'm pretty sure it should work:
              Code:
              extern "C" {
              #include "GraphicsDevice.h" // use <> instead of "" if this is a system header
              }
              If this works, fine, but be aware that your header file is a ticking time bomb. If the function is to take a pointer to a NewDevDesc, then it should be put in the C declaration for the function pointer. Otherwise you may inadvertently assign a function to that function pointer which does not take the appropriate parameter. Doing that will cause undefined results such as seg faulting, memory corruption, odd behaviour or if you are extremely lucky, no apparent effect all the time, and if you are unlucky, no apparent effect some of the time.

              I would be extremely careful with using this header. I personally hate legacy headers like these and have personally chastised companies for leaving them in for as long as they have.

              Hope this helps.


              Adrian
              [*]NOTE: I think in the newer C specs (or may be all of them), you cannot use an ellipsis without at least one parameter to indicate how many parameters are actually passes like the format string use for printf().

              Comment

              Working...