RobotC pointers, enums, structs

Hello, all.

I recently got robotC because I was having issues with the autonomous execution in easyC. I actually wrote all of my code in C, then use the user code blocks to call my C code in each of the 3 easyC functions (so all of my code was actually in other C and H files).

I’ve always been a fan of “good” programming, dividing up code into logical subsystems, using enums to describe states and commands (instead of strings or numbers). Thus, I have a C/H file for each subsystem, with a poke function, and functions to pass data into and out of the subsystem (e.g. an arm has a poke, which does the closed-loop control, and a function to set the state, plus a few other functions).

As easyC actually uses GCC to compile, it wasn’t hard to just use C constructs to define things (e.g. typedef enum) or pass pointers into things, as GCC supports C very well.

I am now trying to port my code into robotC (to make use of the better debugging functions, faster downloads, and better threading, and because of the issues I had with easyC). I am not doing anything really complex (in my eyes), but sometimes it’s just easier to pass a pointer to something than to look back to a variable in global memory.

However, robotC is yelling at me for various things which are valid in C. I’ve got it down to only about 20 errors (and a bunch of warnings which I can ignore for now):

-It dosen’t seem to mind me creating a typedef struct, but it won’t let me set the return type of a function to that structure. In easyC, I passed the variables in as pointers and modified them in the function, but robotC won’t allow me to do it in the C way, so I’m trying to pass data out by returning a structure. Is there any reason for it to not let me return a struct?

-It dosen’t seem to mind most of the typedef enums, but one of them (arm_idg_sen_t) it hates. I declare the enum in the header file (no errors), then create two of them in my arm implementation file, to which it says;

**Error**:Undefined variable 'arm_idg_arm_sen_t'. 'short' assumed.
**Error**:Expected->';'. Found 'idg_trust'
**Error**:Executable statements not valid in 'main' declaration block
**Error**:Undefined variable 'idg_trust'. 'short' assumed.
**Error**:Expected->';'. Found ','
**Error**:Unexpected scanner token-> ','
**Error**:Undefined variable 'idg_debug_last'. 'short' assumed.

Which is strange because another typedef enum defined in the same header file (arm_state_t) is declared only a few lines above I declare the arm_idg_sen_t’s, with no errors there.

It also warns every time I do an operation on idg_trust and idg_debug_last that I can’t use = or == on “short” or “arm_idg_sen_t”

peek & poke, reminds me of my C64 days.

There are no pointers in RobotC. There is no stack in RobotC. Functions in RobotC do not work the same as “normal” C. What can I tell you, it’s not real C.

Would have to seen the code to comment.

You cannot compare an enum to a short, cast the enum like. for example.

typedef enum {
    kVersions = 0,
    kJoystickTest = 1,
} TestMode;
...
...
void MyFunction()
{
    int foo, bar;
    
    if( foo == (short)kVersions )
        bar = 3;
...

}

or (in this case) declare foo as a “TestMode”.

I’m afraid you just have to get used to the fact that RobotC is very much a subset of the C language.

More specific on the struct:
header:


//Structure to hold response
typedef struct {
char pwmLeft;
char pwmRight;
int diff;
} cd_rtn_t;
//Function prototypes
cd_rtn_t do_cheesy_drive(signed int throttle, signed int wheel, unsigned char quickTurn);
cd_rtn_t do_halo_drive(signed char throttle, signed char wheel);

error:

**Error**:Invalid procedure return type
**Error**:Invalid procedure return type

In this case, the function is in a common-use math library that I use on several robots. I’m trying to port all of the code over (from all of the robots), and would like to not have to resort to global variables for returning data.

It lets me return any other datatype (including custom-defined typedef enums), but not structures.

On the issue of enums, I found that it was an error somewhere else in the file causing issues several lines down, which I didn’t notice because it was part of a bulk replace of easyC functions. So, that one was on me.

As far as I know you cannot return structs. The best I could suggest is that you pass the struct into the function as a reference (which is the only type of pseudo pointer allowed). Be aware that RobotC will not allow a struct passed by reference to be passed into a second nested function :frowning:

typedef struct {
char pwmLeft;
char pwmRight;
int diff;
} cd_rtn_t;

//Function prototypes
int do_cheesy_drive(signed int throttle, signed int wheel, unsigned char quickTurn, cd_rtc_t &MyStruct );
int do_halo_drive(signed char throttle, signed char wheel, cd_rtc_t &MyStruct );

That’s unfortunate, as do_halo_drive calls do_cheesy_drive, and either one could be called from higher-level code.

I’ll see what I can do. I’ve honestly never worked on a platform so limiting (everything I’ve ever done has supported passing pointers, even if it didn’t have dynamic memory allocation). Even easyC, which is very limiting in every other way.

I hear you, neither RobotC or EasyC is ideal but you have to remember their target audience is beginning to intermediate programmers.

There is a stack in ROBOTC, it just does not support re-entrant functions.

On a related note, is there anything else that robotC does not support that I should be aware of? Does it support bitwise operators (& ,!, &=, !=, <<, >>)?

There is? Not in the sense that parameters to functions are pushed onto a stack and the function called. All parameters are passed as variables with a fixed memory location. I assume under the hood the VM uses a stack but at the user level I’ve never seen one being used when looking at the assembly code.

Well, look at this thread: ROBOTC

Hmm, well Xander knows a lot more about it than I do but I’m not convinced. I will concede that to be able to call a nested series of subroutines the return address of each one must be stored somewhere, however, to me the major benefit of a stack would be for local variable storage which I know does not happen. Anyway, it’s a moot point as either way we still do not have recursive functions or the ability to pass a variable reference into a function that then get passed onto a second one.