Shop OBEX P1 Docs P2 Docs Learn Events
Is there a guide to writing your own library in SimpleIDE? — Parallax Forums

Is there a guide to writing your own library in SimpleIDE?

maxhirezmaxhirez Posts: 2
edited 2014-02-16 16:25 in General Discussion
I tried writing my own library for SimpleIDE and while I can get it to compile, I can't get it to function. As near as I can figure, I don't understand the cmm .a file or something. In any case, I could use a comprehensive guide to the lib structure for SimpleIDE. I'm coming to it from Arduino, xCode and Ultrix C if that gives you any hints to the mindset, and if anyone has an insight that can solve the problem instantly, here's the folder structure I have built:

-libmyLib
  • -cmm
    • -libmyLib.a
  • -myLib.c
  • -myLib.h
  • -libmyLib.h
The code in the .c file executes flawlessly in a .side project when the functions are instantiated in it, but when I try to call them out of an #include, all the values returned are null. I used xCode as the editor to write the headers and c files and used TextWrangler to build the .a file.

Incidentally, the code is to use a cheaper distance sensor than an official Ping-as a new member, I'm hesitant to be too specific about what I've created. What is the community take on that kind of topic? The sign up rules seemed to be saying you both could and couldn't talk about that sort of thing. It was unclear...

Comments

  • dgatelydgately Posts: 1,630
    edited 2014-02-07 22:00
    maxhirez wrote: »
    I tried writing my own library for SimpleIDE and while I can get it to compile, I can't get it to function.

    The SimpleIDE Help menu will lead you to the SimpleIDE User Guide PDF. Page 30 of the guide contains the start of the "How to Create a Simple Library" section.

    If you followed those instructions and still had the problem, you may need to give more details in order to get some help here.

    dgately
  • jazzedjazzed Posts: 11,803
    edited 2014-02-07 22:33
    Hi. Welcome to the forum.

    SimpleIDE builds the folder structure for you ... if you let it. I seriously recommend SimpleIDE & Project View for library development at least in the beginning. To get started make a new project with Menu -> Project -> New and call the project "libname" in the dialog that opens (use a .c filter or a .cpp file dialog filter) I recommend starting libraries in Documents\SimpleIDE\Learn\Simple Libraries\MyLibs\"libname" Once the libname project is started, the MyLibs\libname folder will contain libname.c and libname.side. Once you compile you should get MyLibs\libname\cmm. So, there is your structure. The User Guide should help understand more details like setting the Create Project Library in the Project Manager's Linker tab.

    Wish I had some water-proof pings for my car - Parallax doesn't offer one. Do you have a waterproof design? I don't know what to say about competing products. Just float a trial baloon. Parallax employees are some of the nicest people on earth - it is very rare that they dissuade any topic. We get into all kinds of discussions around here. Sometimes conversations go off in the woods ... forgive us in advance :)
  • SRLMSRLM Posts: 5,045
    edited 2014-02-08 05:17
    I've taken a slightly different route, since I never saw the point of precompiling Propeller libraries. I created libpropeller so that you can do the following in your project:

    #include "libpropeller/myclass/myclass.h"

    From simple IDE all you have to do is Add Include Path to the root libpropeller folder and you're good to go. This method also works well outside of SimpleIDE in other editors or using a makefile. But please note that this uses a non-standard code organization.
  • David BetzDavid Betz Posts: 14,516
    edited 2014-02-08 05:54
    SRLM wrote: »
    I've taken a slightly different route, since I never saw the point of precompiling Propeller libraries. I created libpropeller so that you can do the following in your project:

    #include "libpropeller/myclass/myclass.h"

    From simple IDE all you have to do is Add Include Path to the root libpropeller folder and you're good to go. This method also works well outside of SimpleIDE in other editors or using a makefile. But please note that this uses a non-standard code organization.
    Are you saying that your library code is in the header files? Doesn't that cause trouble if you have a multi-file project and more than one file includes "myclass.h"?
  • SRLMSRLM Posts: 5,045
    edited 2014-02-08 18:38
    David Betz wrote: »
    Are you saying that your library code is in the header files? Doesn't that cause trouble if you have a multi-file project and more than one file includes "myclass.h"?

    Nope, not a problem. From the C++ language specs (which I quoted here) it says that inline functions only exist once. So it doesn't hurt to include them from multiple sources.
    There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with
    external linkage
    (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member
    of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for
    which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition
    appears in a different translation unit, and provided the definitions satisfy the following requirements...

    With inline headers you typically have much fewer .cpp source files. I usually have 1 main.cpp, and then one .cpp for each class with static variables (which cannot be defined in .h files because those can't have multiple definitions).

    Hmmm. Thinking about it now, it might be better to make it so that the end user does the following in their main.cpp (and only in their main.cpp):

    #include .h files for classes without statics
    #include .cpp files for classes with statics

    Everywhere else #includes the .h file.

    This way, you can have a single propeller-elf-g++ command for compilation, with a single parameter (main.cpp). No need for complicated makefiles, no need for tracking which .cpp files you need to compile. Much easier. It's also a project dependent option: it doesn't change the library (so you can do it the old way if you want).
  • SRLMSRLM Posts: 5,045
    edited 2014-02-08 18:50
    Expanding on my idea from above: I wonder if we can repurpose the preprocessor to include the .cpp files for us? I'm thinking something like this:

    MyClass.h
    #IFNDEF MYCLASS_H__
    #DEFINE MYCLASS_H__
    
    #IF __INCLUDE_LEVEL__ == 1
    #include "MyClass.cpp"
    #ENDIF
    
    class MyClass{
    
    };
    
    #ENDIF // MYCLASS_H__
    

    main.cpp is level 0, so whatever it includes is level 1. Assuming main.cpp includes things only once, then there will be at most a single copy of the headers .cpp file. This does assume a single compilation unit, but that's what I'm going for anyway.

    Reference: Predefined Preprocessor Macros:
    http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
  • SRLMSRLM Posts: 5,045
    edited 2014-02-08 19:17
    So that works, but only as the following:

    MyClass.h
    #IF __INCLUDE_LEVEL__ == 1
    #include "MyClass.cpp"
    #ENDIF
    
    #IFNDEF MYCLASS_H__
    #DEFINE MYCLASS_H__
    
    class MyClass{
    
    };
    
    #ENDIF // MYCLASS_H__
    

    You have to move the MyClass.cpp include out so that your main.cpp inclusion of MyClass.h doesn't have to be first. Otherwise, other classes (ClassThatUsesMyClass.h) will include it at a non-level 1 include level but define the variable that prevents it from being included again.

    But, if we're going to be in a single compilation unit why not just include it directly:

    MyClass.h
    #IFNDEF MYCLASS_H__
    #DEFINE MYCLASS_H__
    #include "MyClass.cpp"
    
    class MyClass{
    
    };
    
    #ENDIF // MYCLASS_H__
    
  • SRLMSRLM Posts: 5,045
    edited 2014-02-08 19:32
    Ok, here's my final solution:

    MyClass.h
    #ifndef MYCLASS_H__
    #define MYCLASS_H__
    
    class MyClass{
    
    };
    
    #ifdef SINGLE_TRANSLATION_UNIT
    #include "MyClass.cpp"
    #endif
    
    #endif // MYCLASS_H__
    

    First off, there are no side effects. This is opt-in. Once you do, you'll be able to compile like follows:
    propeller-elf-gcc -D SINGLE_TRANSLATION_UNIT main.cpp
    

    The compiler will then, automatically, pull in all the code needed as long as your include paths are set up correctly (or it's local). There's no problem with multiple definitions since there's only one translation unit. It works well, and in my program dropped the size down 16 bytes :) I think I'll add this to libpropeller (there's only one .cpp anyway...).

    One side note: I'm still looking for a good .S solution (for cog code). I haven't figured out a way to auto include that from the .h files.
  • jazzedjazzed Posts: 11,803
    edited 2014-02-08 21:18
    Hi Cody,

    Can you provide a small example application that uses some libpropeller code (and build instructions with path setups, etc...) using the last solution?

    I have something to try with it.

    Thanks.
  • SRLMSRLM Posts: 5,045
    edited 2014-02-09 20:28
    jazzed wrote: »
    Can you provide a small example application that uses some libpropeller code (and build instructions with path setups, etc...) using the last solution?

    I can, but it will have to wait until Tuesday. I've loaned out all my Propeller boards.
  • Courtney JacobsCourtney Jacobs Posts: 903
    edited 2014-02-10 10:23
    maxhirez,

    We are currently working to release a tutorial series all about Simple Libraries on our Learn site, and it will include a section on creating your own Simple Libraries.

    Although the series is not quite ready for publishing yet, expect to see it make its debut in the very near future.
  • maxhirezmaxhirez Posts: 2
    edited 2014-02-16 16:25
    Best answer. Thanks!
Sign In or Register to comment.