![]() |
Understanding the Source code
I'm a pretty proficient programmer (most of my experience is with C#), but I'm still finding myself stumped by some of the source code. I'm hoping that if I understand the source I can implement new classes as necessary and use proper conventions (especially where error handling is concerned).
First question: Macros. FRC apparently (and inexplicably) has made extensive use of macros. I'm not extremely familiar with them, but they seem to serve many purposes. The first one I came across: "START_ROBOT_CLASS(IterativeDemo);" at the bottom of the demo class. This references RobotBase.h, which has: Code:
#define START_ROBOT_CLASS(_ClassName_) \Second question: Macros. Heh, sorry, I mean Macros that do error handling. The next major macro confusion is with the "wpi_assert"s and "wpi_fatal"s that are sprinkled across the code. One example in RobotDrive.cpp: Code:
void RobotDrive::SetInvertedMotor(MotorType motor, bool isInverted)Code:
#ifdef WPI_STATUS_DEFINE_STRINGSSorry if this was a lot of questions... Basically, I want to know: -What happened to main() and what is the START_ROBOT_CLASS macro doing -How the wpi_assert and _demands handle errors |
Re: Understanding the Source code
Quote:
The program's entry point is FRC_UserProgram_StartupLibraryInit. This is what the LabVIEW Run-Time calls when it loads the user program. The START_ROBOT_CLASS macro sets up a "user class factory", which is a function that returns a pointer new instance of your robot class. Additionally, it creates the entry point function, FRC_UserProgram_StartupLibraryInit. This entry point calls RobotBase::startRobotTask() with a pointer to the "factory" function. From here, a new task is spawned to run the user program. This task creates an instance of your Robot class and calls its StartCompetition() function. I'm not sure I quite understand the reason behind spawning off this new task, but I believe it somehow makes it easier to debug. Quote:
|
Re: Understanding the Source code
Quote:
As for your other complaints -- I hear ya brother. Gotta love C++. |
Re: Understanding the Source code
Quote:
Thank you, Matt! With those pointers in the right direction (heh), I think I understand the code now. So, just to recap: -START_ROBOT_CLASS, through many convolutions, defines the entry point FRC_UserProgram_StartupLibraryInit, which is called from external code (on the cRIO), which: -Spawns a new task running an instance of the robot class Do I have that right? OK, so, in lieu of using try-catch blocks, I should use wpi_assert around conditionals that try to trap errors like null pointers? From what I can tell, this prints a message to the console (and puts a condition on the stack?). So, if I wanted to flush the error stack, I'd use wpi_assertCleanStatus. What's the difference between wpi_assert and wpi_fatal? |
Re: Understanding the Source code
Quote:
Quote:
Additionally, if a debugger is attached, when the assert condition is false then the debugger usually takes over at that point and you can examine the local variables and see what happened that caused the condition to be false. Now why is that useful? When you're making something, its useful to put in little checks basically saying "this condition should never happen, if it does then we need to immediately stop execution". You can also put in more expensive checks in there that only run in the debug build, so that way the code is more optimized in the release build (since, the checks are not done if NDEBUG is defined). Code:
switch (some_val)Code:
assert((some_val == 1 || some_val == 2) && "this should never be a different value");Look at Utility.cpp in WPILib for the implementation. |
Re: Understanding the Source code
Sounds good, thanks.
I've been wondering what the keyword extern does. I see "extern "C"" a lot. None of the C++ references really provide a good explanation in the context of this code. |
Re: Understanding the Source code
Quote:
The extern "C" gives a hint to the compiler that the separate file will be using C conventions, so the linker doesn't get confused trying to connect C and C++ object files together without the appropriate conversion. |
Re: Understanding the Source code
Like the words "static" and "const", "extern" is somewhat context-dependent in C++. For more: http://en.wikipedia.org/wiki/Extern
|
Re: Understanding the Source code
Ah, thanks.
Something that my programming teacher asked me and I had no idea: does the cRIO use interrupts to handle input from joysticks (like a Windows environment does)? |
Re: Understanding the Source code
I (a fellow C#er) don't personaly like the unsafe nature of C++, but alas!
Anyhow, in the C Programming guide: Quote:
so no exceptions look for c complilers operations (google it) for #ifndef and #define, they are compiler constants. |
Re: Understanding the Source code
Agreed, C++ is...well, a bit low-level after working with C# for so long.
Quote:
Quote:
|
Re: Understanding the Source code
Quote:
also Quote:
Code:
if i have not defined "WPI_STATUS_DEFINE_STRINGS" then |
Re: Understanding the Source code
Thanks, I understood what the macro was doing (as far as conditional includes and substituting the values were concerned), my question was why. I didn't see what the wpi_v_##label did, how it was used, or where ##label was defined.
EDIT: I guess when I made the original post I didn't know what you were explaining. Sorry for the confusion. |
Re: Understanding the Source code
the ## is the preprocessor concat symbol
so in S(label, offset, message) const int wpi_v_##label = offset; const char *wpi_s_##label = message ; if you say S(MyLabel, 1,"Message of mine") it will replace the vars so it looks like this const int wpi_v_MyLabel = 1; const char *wpi_s_MyLabel = "Message of mine"; |
| All times are GMT -5. The time now is 02:57. |
Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Copyright © Chief Delphi