Function Pointers in ROBOTC

Hello, I mentioned in another thread that I had been working with structs and function pointers in ROBOTC recently to try to make structs, similar to classes, for each subsystem on my robot. I tried compiling my code today and had some strange issues. Here is the relevant portion of code …


typedef struct
{
  void *forward( float dist );
  // other data too, not really significant to the problem
} MecanumDrive;

void driveForward ( float dist ); /*prototype of function to drive forward defined later*/

void initMecanumDrive ( MecanumDrive *drive )
{
  // initilizes all fields, etc ...
  drive->forward = &driveForward; // this is where the issues are
}

There are other functions but, I’m just going to focus on this one because I can fix the others once I fix this one. When I try to compile the code, it gives me an error on the line where I try to initialize the function pointer ‘forward’. It says that forward is not a field of the struct reference drive. Does anyone with more experience know what I am messing up with the assignment here? Thanks in advance for your help.

Pointers to functions are not supported, that’s one area where the EasyC compiler is still superior. Long story but functions in ROBOTC are not called in the traditional way by putting an address in the program counter register. I have not found any clever workarounds yet either, the best I could do in our drive library was call different functions based on another variable, for example.

void
DriveSystemDrive( int forward, int turn, int right = 0 )
{
        switch( theDrive.type )
        {
        case      Mecanum4Motor:
        case      Mecanum4MotorFieldCentric:
            DriveSystemMecanumDrive( forward, turn, right );
            break;

        case      Arcade2Motor:
        case      Arcade4Motor:
            DriveSystemArcadeDrive( forward, turn );
            break;
        default:
            break;
        }
}

theDrive.type is set in an initialization routine depending on the type of drive the robot has, a generic function is called to send the drive parameters and the specific drive code is then called depending on what the drive type is.

Thanks for the reply, it’s too bad that ROBOTC doesn’t support function pointers.

It’s unfortunate, I was not happy but it is what it is. This gives you an idea of what is happening. A program like this.

void f1() {int x = 123; }
void f2() {int x = 456; }
   
task main()
{
    f1();
    f2();
}

compiles to byte code like this.

void f1() {int x = 123; }
**Info***:'x' is written but has no read references
//
//Code segment: f1(); Procedure: 0
// 
0000: CA007B00                 x:S00(short) = 123                 
0004: 7B                       Return()                            // f1()
void f2() {int x = 456; }
**Info***:'x' is written but has no read references
//
//Code segment: f2(); Procedure: 1
// 
0000: CA00C801                 x:S00(short) = 456                 
0004: 7B                       Return()                            // f2()
   
task main()
//
//Code segment: main(); Task: 0
// 
0000: 614000                   StopAllMotors()                    
0003: 6732000000000100         configureSerialPort(UART0, uartSystemCommPort)
000B: 6732000100000000         configureSerialPort(UART1, uartNotUsed)
0013: 6732000200000300         configureSerialPort(UART2, uartVEXLCD)
001B: 676701001C               ClearSensors(in1..I2C_8)           
0020: 676D01000A               ClearMotors(port1..port10)         
{
    f1();
0025: 170000                   callSub(f1, 0)                     
    f2();
0028: 170100                   callSub(f2, 0)                     
}
002B: 614000                   StopAllMotors()                    
002E: 7B                       Return()                            // main()
0000: 7B                       Return()                            // _main__()

ROBOTC gives each function a number starting at 0 in the order they appear in the source file. It knows what the number of each function is and then uses this in the subroutine call, there are a maximum of 256 functions (if i remember correctly) possible but so far I have never been close to that limit.

Looking at that byte code, it wouldn’t be hard to add support for a type of function pointer.

this is robotc’s own virtual machine so all they need is to add an indirect version of callSub say callSubInd and a new variable type functionpointer which is in effect a byte which stores the byte index of the function. callSubInd is then just passed a reference to the functionpointer.

anyway just a thought
Steve

Which it was that easy, here is the official reason why it’s not implemented.

Unofficial reason is that it’s a lot of work and has not been a high priority.

One way is to implement your own dispatch table/code and call the function based on some variable, that’s more or less what you were suggesting.

Yes I saw that :), However a lot of the early machines I programmed had the same arcutecture (ok N64 was probably the only one I programmed in C, and PS1 stored it all in ram) but they had no problem with function pointers. Ok you can’t use self modifying code, but since the day of caches you couldn’t anyway… and the program still has to access ram to get function parameters etc. I wonder where the virtual machines PC is stored…

hmmm

yes but as far as I can see the only way to do this is create a function that knows about everything… although… thinking about it, you could give each class its own dispatch table/code.
Ok the master dispatch code would have to know about all the classes, but at least it wouldn’t have to know specifcally about each function in a class, and you could then allow classes to be derived… although sort of upside down.

I shall have to have a think :slight_smile:
Steve