8 Replies Latest reply on Oct 20, 2014 2:02 AM by mhahn

    link errors using MRAA c++ with multiple source files

    KurtE

      I thought it would be fun to port the version the Adafruit_ILI9341 display code including the touch screen code to be able to be compiled using makefiles on the Edison instead of arduino IDE, so I started porting the code over to MRAA.  I have a few different source files using the MRA classes (gpio, spi) and when I try linking the code into a test program, it errors out with a bunch of duplicate symbols...

       

      So to verify this I took the sample program Blink_IO.cpp that is one of the mraa library and generated a makefile for it.  I then built and ran it on my Edison.  I then, split the example into two files, where I moved the setting of the IO pin to the second file.    The whole content minus some comments at top

      #include <signal.h>

      #include <stdio.h>

      #include <stdlib.h>

      #include <stdlib.h>

      #include <unistd.h>

       

      #include "mraa.hpp"

      #define DEFAULT_IOPIN 13

      #define DEFAULT_IOPIN2 2

       

      mraa_result_t  SetIOPinVal(mraa::Gpio* gpio, int iVal) {

          return gpio->write(iVal);

      }

       

      I updated the makefile to compile both files and link.  Also changed the primary file to call this instead of doing gpio->write( and added function prototype.  Compiled the program and sure enough the link fails again, with:

      i586-poky-linux-g++ -pedantic -g -O2 -fno-rtti -I.-c -o Blink-IO.o Blink-IO.cpp

      i586-poky-linux-g++ -pedantic -g -O2 -fno-rtti -I.  Blink-IO.o Blink-IO2.o -o blinkio -L/usr/lib/arm-linux-gnueabihf -L../library -L../Adafruit_ILI9341C -lpthread -lmraa

      Blink-IO2.o: In function `mraa::getVersion()':

      /usr/include/mraa/common.hpp:48: multiple definition of `mraa::getVersion()'

      Blink-IO.o:/usr/include/mraa/common.hpp:48: first defined here

      Blink-IO2.o: In function `mraa::setPriority(unsigned int)':

      /usr/include/mraa/common.hpp:64: multiple definition of `mraa::setPriority(unsigned int)'

      Blink-IO.o:/usr/include/mraa/common.hpp:64: first defined here

      Blink-IO2.o: In function `mraa::getPlatformType()':

      /usr/include/mraa/common.hpp:74: multiple definition of `mraa::getPlatformType()'

      Blink-IO.o:/usr/include/mraa/common.hpp:74: first defined here

      Blink-IO2.o: In function `mraa::printError(mraa_result_t)':

      /usr/include/mraa/common.hpp:84: multiple definition of `mraa::printError(mraa_result_t)'

      Blink-IO.o:/usr/include/mraa/common.hpp:84: first defined here

      Blink-IO2.o: In function `mraa::pinModeTest(int, mraa_pinmodes_t)':

      /usr/include/mraa/common.hpp:95: multiple definition of `mraa::pinModeTest(int, mraa_pinmodes_t)'

      Blink-IO.o:/usr/include/mraa/common.hpp:95: first defined here

      Blink-IO2.o: In function `mraa::adcRawBits()':

      /usr/include/mraa/common.hpp:106: multiple definition of `mraa::adcRawBits()'

      Blink-IO.o:/usr/include/mraa/common.hpp:106: first defined here

      Blink-IO2.o: In function `mraa::adcSupportedBits()':

      /usr/include/mraa/common.hpp:116: multiple definition of `mraa::adcSupportedBits()'

      Blink-IO.o:/usr/include/mraa/common.hpp:116: first defined here

      Blink-IO2.o: In function `mraa::setLogLevel(int)':

      /usr/include/mraa/common.hpp:127: multiple definition of `mraa::setLogLevel(int)'

      Blink-IO.o:/usr/include/mraa/common.hpp:127: first defined here

      collect2: error: ld returned 1 exit status

      makefile:53: recipe for target 'blinkio' failed

       

      Not sure of the best approach to take, convert to using c functions instead?  Do my own wrapper functions which encapsulate the SPI and IO pins into one source file?

       

      Sorry for maybe not easy to read.  Not sure how to do things yet on this forum software.  Things like code tags...

       

      Thanks

        • 1. Re: link errors using MRAA c++ with multiple source files
          faceplant

          The problem is that all those functions are declared in an include file, so they're getting defined in multiple files.  Very bad coding practice!

           

          They either need to be moved to a source file or declared static or inline.  They look to be just wrapper functions, so declaring them as static shouldn't be a problem.  You could also add inline, but they will probably be inlined anyway if any optimization is turned on.

          • 2. Re: link errors using MRAA c++ with multiple source files
            KurtE

            Thanks,

             

            I went up and edited the file: /usr/include/mraa/common.hpp

            and added inline to each of the functions and it now builds.

             

            I now have a version of the Adafruilt_ILI9341 library (as well as GFX) built  using this and I have a version of their graphictest program built using my stuff, which is starting to work.

             

            However: having issues that the test program will go through and fill the screen with several different colors correctly and then nothaning.  Can abort program and restart and then it goes farther, showing text, start drawing the lines and the like.  But when running this program it not typically make it to the end, but will reboot the Edison which a user level program should not be able to do.

             

            Found first issue with my code:  found that spi->write(mybuf, cnt), returns a chr *, which it creates using malloc.  So needed to add free calls to return this memory. Wish there was a version like the Arduino IDE call for transfer that you can pass in your buffer to receive the data to avoid malloc and frees...   Fixed my code to detect non-NULL values and do the free, but program is still rebooting Edison.

             

            FYI - I have uploaded my current stuff up to my Raspberry_Pi project on github (KurtE/Raspberry_Pi · GitHub)

             

            Kurt

            • 3. Re: link errors using MRAA c++ with multiple source files
              tektronix

              faceplant wrote:

               

              The problem is that all those functions are declared in an include file, so they're getting defined in multiple files.  Very bad coding practice!

               

              They either need to be moved to a source file or declared static or inline.  They look to be just wrapper functions, so declaring them as static shouldn't be a problem.  You could also add inline, but they will probably be inlined anyway if any optimization is turned on.

               

              Should I bring this up as a problem issue on github for mraa ?

              • 4. Re: link errors using MRAA c++ with multiple source files
                tektronix

                I tried this way and it worked for me without having to modify the mraa source files using inline.

                 

                Instead of #including  with .hpp, I.E. #include "mraa/common.hpp"

                I instead included its .h file. I.E. #include "mraa/common.h"

                 

                doing this it took care of everything for me, compiled and now works just fine without any mods needed to the mraa source files using inline. 

                I then (but you dont have to) created a "headers.h" file. In there i have the following.

                #ifndef HEADERS_H_

                #define HEADERS_H_

                 

                #include <signal.h>

                #include <stdio.h>

                #include <stdlib.h>

                #include <string.h>

                #include <signal.h>

                #include <stdint.h>

                #include <unistd.h>

                 

                #include "mraa/common.h"

                #include "mraa/spi.h"

                #include "mraa/gpio.h"

                 

                extern mraa_spi_context spi;

                extern mraa_gpio_context gpio;

                 

                #include "mcp23s17.h"

                 

                #define MS    (1000)

                 

                #endif /* HEADERS_H_ */

                 

                 

                Then in my main app i just have one #include "headers.h", and in my other source file that takes care of the SPI calls I put the same in there as well.

                The trouble for me is that i need both source files to twiddle some I/O pins. Which is what created this whole problem in the first place.

                In main, i made these global, and in my headers.h file i externed them so now all sources can use them.

                mraa_spi_context spi;

                mraa_gpio_context gpio;

                • 5. Re: link errors using MRAA c++ with multiple source files
                  KurtE

                  Maybe I should?   I have made my own fork on github (KurtE/mraa · GitHub)

                   

                  Where I have so far made a couple of deltas, that maybe I should try adding a pull request back to the main branch

                  a) Added the inline for these functions which allow my simple test program to build.  Note for my main stuff I changed over to calling the C functions as the C++ class simply called these anyway...

                   

                  b) Added some defines for UART for the edison module, so the call to uart = mraa_uart_init(0);

                  would not fail

                   

                  Note: to use my branch (or the main branch), what I did was to download the github project to my edison, created a build directory under it, then did a cmake using the suggested option to install in place linker looks at ( -DCMAKE_INSTALL_PREFIX:PATH=/usr), then did a make followed by a make install.

                   

                  Note: I don't believe cmake is installed by default, I downloaded it form the cmake org.

                   

                  Kurt

                   

                  Update: I did put in a pull request for this.  As mentioned, putting the functions directly in header file may be an issue, but the inline does help.

                  • 6. Re: link errors using MRAA c++ with multiple source files
                    KurtE

                    The inline fix was migrated the the official MRAA github.(intel-iot-devkit/mraa · GitHub)

                     

                    Not sure when it will make it into a release, but you can always download it from github and build.

                    • 7. Re: link errors using MRAA c++ with multiple source files
                      tektronix

                      There are no instructions for doing this though.

                      Still learning Linux, so though i would like to use the latest updates i don't know how to implement them.

                      • 8. Re: link errors using MRAA c++ with multiple source files
                        mhahn

                        just "opkg update && opkg upgrade" after correctly set mraa in /etc/opkg folder

                         

                        (e.g.

                        cat > /etc/opkg/mraa-upm.conf << EOF
                        src mraa-upm http://iotdk.intel.com/repos/1.1/intelgalactic

                        EOF)


                        Latest package build from yesterday. So should be pretty recent