Frustrations With Porting Spin to C (Using FlexGUI) [SOLVED]
JonnyMac
Posts: 9,102
Having the desire to share my large library of Spin objects with those who prefer C, I decided to start by porting a my most recent objects for the TM1637 and TM1638 display drivers. I wrote Spin objects and test code for both devices in less than a day. Now, I've been programming in Spin -- almost every day -- for the last 13 years, so I'm pretty good at it.
While I don't routinely use C, I have used it enough to understand all but the most obtuse syntax rules, and over the years I have ported a lot of C code from other micros to the Propeller. Going from Spin -- except for very special cases -- is supposed to be easy; C dominates the programming world, it syntax is light and easy, etc., etc....
...my experience this week has been nothing but frustration.
I'm looking for guidance. And by that, I don't mean telling me to run my Spin code through some automated tool to do the conversion -- that's antithetical to deep leaning in my opinion. This exercise in frustation has been about learning, but I've had too much in the way of frustration and too little in the way of learning (something new).
I did get my C library for the TM1637 (2-wire) working after pounding my head on the desk dealing with SimpleIDE. Today I decided to try it in FlexGUI and, to my surprise, the frustrations are starting all over. I really didn't expect this after getting it to work under SimpleIDE.
These are the steps I took:
1. I created a separate library folder so that my custom code wouldn't be wiped out by replacing the FlexGUI folder. (C:/MyPrograms/jm_libc)
2. I copied my .h and .c library files to that folder
3. I added that folder to the library folders list in FlexGUI
4. I wrote a little test code just to test the library connection
Click "Compile for P1" -- so far, so good. Next, I added a line to connect to the device.
... and things blow up. Why?
Clearly, that function IS defined and implemented -- why is the compiler unhappy here?
While I don't routinely use C, I have used it enough to understand all but the most obtuse syntax rules, and over the years I have ported a lot of C code from other micros to the Propeller. Going from Spin -- except for very special cases -- is supposed to be easy; C dominates the programming world, it syntax is light and easy, etc., etc....
...my experience this week has been nothing but frustration.
I'm looking for guidance. And by that, I don't mean telling me to run my Spin code through some automated tool to do the conversion -- that's antithetical to deep leaning in my opinion. This exercise in frustation has been about learning, but I've had too much in the way of frustration and too little in the way of learning (something new).
I did get my C library for the TM1637 (2-wire) working after pounding my head on the desk dealing with SimpleIDE. Today I decided to try it in FlexGUI and, to my surprise, the frustrations are starting all over. I really didn't expect this after getting it to work under SimpleIDE.
These are the steps I took:
1. I created a separate library folder so that my custom code wouldn't be wiped out by replacing the FlexGUI folder. (C:/MyPrograms/jm_libc)
2. I copied my .h and .c library files to that folder
3. I added that folder to the library folders list in FlexGUI
4. I wrote a little test code just to test the library connection
#include "propeller.h" #include "tm1637.h" void main() { while (1) { } }
Click "Compile for P1" -- so far, so good. Next, I added a line to connect to the device.
#include "propeller.h" #include "tm1637.h" void main() { tm1637_setup(4, 5, 6); while (1) { } }
... and things blow up. Why?
"C:/MyPrograms/flexgui/bin/fastspin" -l -O2 -I "C:/MyPrograms/flexgui/include" -I "C:/MyPrograms/Parallax Inc/Propeller Tool v1.3.2/Library" -I "C:/MyPrograms/jm_libc" "D:/programming/C/tm1637_demo.c"
Propeller Spin/PASM Compiler 'FastSpin' (c) 2011-2019 Total Spectrum Software Inc.
Version 4.0.5 Compiled on: Dec 19 2019
tm1637_demo.c
/programming/C/tm1637_demo.c:14: error: unknown identifier tm1637_setup used in function call
/programming/C/tm1637_demo.c:14: error: Unknown symbol tm1637_setup
child process exited abnormally
Finished at Sun Dec 22 12:03:55 2019
Clearly, that function IS defined and implemented -- why is the compiler unhappy here?
Comments
Can I start writing something I wanted to write since a long time ? Don't want to offend anyone.
I'm amazed at how much efforts people put into learning all the new weird and esoteric languages but always complain about how diffcult and obscure C (or C++) is.
Like any other language, C requires learning. How do you have learned to program in Spin ? I believe you weren't born with Spin skills already into your brain, you readed some manual, wrote some elementary code, experimented with it, gradually enhanced your skills. You need to do the same with C.
In my case, I'm always frustraded when I have to write Spin code, a language I find with a lot of nonsense and with that weird convention that makes indentation a requirement! However I'm programming in C since I was 15 (now I'm 50) and Spin occasionally only when absolutely needed, so most of my frustration comes from inexperience.
Your main error here is that you are relying on an IDE that hides most of the underlying details of the C build chain. SimpleIDE, like the Arduino IDE (don't know FlexGUI but I believe it does something similar), implements some "magic" to automatically build and link libraries, however these details needs to be known otherwise you'll always fail to understand why your code doesn't work as you expect.
The first thing you need to do is throw away the IDE and compile your code with command line tools, like:
This command will compile and link all the source codes and produces the elf executable. You should also need to know what the command line parameters means because they can have effects on pre-compiled libraries if not used properly.
Now you need to use the loader to write the binary to the Propeller eeprom:
Once you have practiced with these, you can learn how to produce object codes from source files, how to build a library and how to link them to other sources to produce the final executable. Learning how to use a Makefile is also very important with C. In other words, start with the basics.
After that you can start to use an IDE that does some of the work for your hiding the details (but I believe that you won't do that).
About your specific problem, the source files you have attached can be compiled without problems (well, there is a missing semicolon but the compiler will tell you where). If SimpleIDE (or something else) complains that it can't find a method probably means that it can't link the library, maybe because you didn't follow the convention used by that IDE to find the libraries.
You compile only "tm1637_demo.c" and "tm1637.h", so the compiler knows the name of function "tm1637_setup", but the function is not compiled.
You have to add "C:/MyPrograms/jm_libc/tm1637.c to your commandline.
This should compile, after adding the semicolon:
"C:/MyPrograms/flexgui/bin/fastspin" -l -O2 -I "C:/MyPrograms/flexgui/include" -I "C:/MyPrograms/Parallax Inc/Propeller Tool v1.3.2/Library" -I "C:/MyPrograms/jm_libc" "D:/programming/C/tm1637_demo.c" "C:/MyPrograms/jm_libc/tm1637.c
Problem of flexgui is, as I know, that you can not make a project and add all your files you need.
Now, before SimpleIDE became "simple", there was only a "Project Manager" mode. As I recall, in SimpleIDE, the bottom left side, if you click on the icon, it will put SimpleIDE into Project Manager mode. Now the IDE becomes not so "simple", you can do a lot more stuff.
For your tm1637 program you could have: In the Project Manager window, on the left side you would see something like:
tm1637.side
tm1637.c
pressing the right button of the mouse allows you to add a file to the build chain. In this case you may want to change your tm1637. c to maybe tm1637_p.c and that would be added to the build chain.
I have not tried doing that, but I believe that should compile your program correctly.
Yea, to bad jazzed did not think about adding the ability of adding PASM code and have the program convert it to some functional C code. Man, that would have simplified the use of existing PASM drivers code. I bet jazzed probably mentioned that to Parallax, but they more than likely shut him down.
Ray
dgately
Pain though...
Guess you have to have "Project" file for C...
@dnalor This is where I'm confused; my expectation that including the custom library path would handle that. I wonder if this is why Ray thinks FastSpin may have a bug.
@"Dave Hein" and @dgately Thank you for your suggestions.
I'm just used to doing C++ in Visual Studio where I have all the files I need in the project anyway...
(1) #include just literally copies the contents of the .h file into the source at the point where the #include is seen. In standard C #include does nothing to arrange that the libraries described by the .h file will actually be linked into the code.
(2) This is confusing for newcomers because the "standard" C libraries (described by <stdio.h> and similar header files) *are* automatically linked, so they naturally expect that their own libraries will get this treatment. But they don't.
(3) Different compilers/toolchains/IDEs have different ways of overcoming this problem. The portable solution is to use a command line or an IDE that lets you link multiple files together, and to specify all of the source files and libraries that you need explicitly. SimpleIDE does some kind of magic behind the scenes that (usually) causes it to compile a .c file when the corresponding .h is included, but I don't know exactly what that is. Visual C has a #pragma to specify that a library should be linked when a .h is included; I'll probably (eventually) try to implement something like that. For now, FlexC has a special define _IMPL() (defined in <compiler.h>) that says where a function is implemented. So if you write something like: then a #include "tm1637.h" will automatically make sure tm1637.c is compiled as well. This is non-portable, but unfortunately there is no portable solution in C .
Thanks for the clarification. I've got to get back to being productive, so my adventures in programming the Propeller with C -- for the time being, anyway -- have come to an end.