Menu

Need help with integrating an Ardino library

2015-06-19
2015-06-21
  • Martin Bachmann

    Martin Bachmann - 2015-06-19

    I started with haikuVM on Arduino today. First examples went well and I started to love it :) Then I tried for quite some time now to integrate an existing arduino library (LedControl). I followed the bundled LiquidCrystal.java example and some try and error.

    I assume the used mechanism (cConstructor / cobject) maps any methods with the same signature to the corresponding method of the c++ instance, is that correct?

    Where need the .h/.cpp files to be placed to get picked up? I tried in the same folder as the java files, which resulted in "multiple definitions found" errors:

    ./LiquidCrystal.o: In Funktion `LiquidCrystal::setRowOffsets(int, int, int, int)':
    LiquidCrystal.cpp:(.text._ZN13LiquidCrystal13setRowOffsetsEiiii+0x0): Mehrfachdefinition 
    von `LiquidCrystal::setRowOffsets(int, int, int, int)'
    

    If I placed them in the clib folder, they're not found.

    A little how-to compile that example would be very much appreciated.

    Thanks - Martin

    PS: here's what I've tried, besides the LiquidCrystal example: https://dl.dropboxusercontent.com/u/1337791/LEDMatrix.zip
    PPS: Yes, c/c++ noob here, maybe for the senior it's all obvious.

     
    • genom2

      genom2 - 2015-06-21

      Hello Bachiander,

      oh, I see you took 'examples:processing.libraries.LiquidCrystal.LiquidCrystal' as a blueprint and started to write your own code. (Because it's not working I have to replace or delete it in the future.)

      First: it's ok if you put your focus on JNI and C/C++ code when using HaikuVM. (In this case the Java part of the interface degenerates to a proxy to the real C subject.) But I would like to see putting focus on Java code. Here is an example of LiquidCrystal in Java 'gallerie:avr.gallerie.user.cvdenzen.arduino.libraries.liquidcrystal.LiquidCrystal'.

      Second: smooth interfacing with C++ objects is not supported yet, neither is annotation @NativeCppMethod (today sadly it's just a noop). It's in an experimental stage. See my experiments in:
      examples:arduino.tutorial.NativeCVariableEnhanced
      myCProject:/tutorials/NativeCVariableClass.cpp

      1)

      I assume the used mechanism (cConstructor / cobject) maps any methods with the same signature to the corresponding method of the c++ instance, is that correct?

      Not quite right. You are expecting to much magic. You have to look at it thru Java glasses, like HaikuVM does. Please take a look at this tutorials: http://haiku-vm.sourceforge.net/#[[Tutorial%20JNI]]

      1.1) Sadly cConstructor / cobject have no meaning for HaikuVM!
      1.2) Sadly until today annotation @NativeCppMethod is a noop.
      1.3) When using attribute native, HaikuVM only generates empty JNI C code blueprints into file 'haikuJNI.c'. You have to cut&past them into your C files and fill out the gap (See '// TODO: insert your code here' in the function body below).

      ############## Java
      private native static Object cConstructor(int dataPin, int clkPin, int csPin, int numDevices);
      
      ############## HaikuVM for you in haikuJNI.c
      JNIEXPORT jobject Java_avr_gallerie_user_bachiander_LedControl_cConstructor JNICALL
        (JNIEnv *env, jclass obj, jint arg1, jint arg2, jint arg3, jint arg4)
      {
          // TODO: insert your code here
          return NULL;
      }
      

      1.4) You get more out of HaikuVM and closer to what you want, if you use the supported annotation @NativeCppFunction. Now HaikuVM fills out the gap with some default C code and puts the whole thing into file 'nativeCFunctions.cpp'.

      ############## Java
      @NativeCppFunction
      private native static Object cConstructor(int dataPin, int clkPin, int csPin, int numDevices);
      
      ############## HaikuVM for you in nativeCFunctions.cpp
      JNIEXPORT jobject Java_avr_gallerie_user_bachiander_LedControl_cConstructor
        (JNIEnv *env, jclass obj, jint arg1, jint arg2, jint arg3, jint arg4)
      {
          return cConstructor(arg1, arg2, arg3, arg4);
      }
      

      1.5) This is still not what you want. Because C function 'cConstructor(arg1, arg2, arg3, arg4)' is undefined. What you really want is to call the constructor of the C class 'LedControl'. You can overwrite the default C code by using member cImpl of annotation @NativeCppFunction. This enables you to merge your own C code into the generated file 'nativeCFunctions.cpp'.

      ############## Java
      @NativeCHeader(cImpl = "#include <LedControl.h>")
      public class LedControl {
      ...
      @NativeCppFunction(cImpl = "return (jobject) new LedControl(arg1, arg2, arg3, arg4);")
      private native static Object cConstructor(int dataPin, int clkPin, int csPin, int numDevices);
      
      ############## HaikuVM for you in nativeCFunctions.cpp
      //////////////////Start of user code given per Java class by cImpl
      #include <LedControl.h>
      //////////////////End   of user code given per Java class by cImpl
      ...
      JNIEXPORT jobject Java_avr_gallerie_user_bachiander_LedControl_cConstructor
        (JNIEnv *env, jclass obj, jint arg1, jint arg2, jint arg3, jint arg4)
      {
      //////////////////Start of user code given by cImpl
      return (jobject) new LedControl(arg1, arg2, arg3, arg4);
      //////////////////End   of user code given by cImpl
      }
      

      1.6) Now, when we focus for example on method setLed(..) it becomes ugly. Because if you want to call the setLed(..) C++ member method, you have the need to access the Java field cobject to reach your C++ object. This in turn means you have to mess around with a lot of JNI stuff. (Which HaikuVM supports to some very low degree.) Don't try it, it will not work. But here is the idea:

      ############## Java
      @NativeCHeader(cImpl = 
          "#include <LedControl.h>\n"+
          "typedef struct avr_gallerie_user_bachiander_LedControl {\n"+
          "  jobject    cobject; //Ljava/lang/Object;\n"+
          "} avr_gallerie_user_bachiander_LedControl;")
      public class LedControl {
      ...
      @NativeCppFunction(cImpl = 
          "#define cls avr_gallerie_user_bachiander_LedControl\n" +
          "jfieldID fid = (*env)->GetFieldID(env, cls, cobject, \"Ljava/lang/Object;\");\n" +
          "if (fid == 0)\n" +
          "    return;\n" +
          "LedControl* cobj = (LedControl*)((*env)->GetObjectField(env, obj, fid));\n" +
          "cobj -> setLed(arg1, arg2, arg3, arg4);")
      public native void setLed(int addr, int row, int col, boolean state);
      
      ############## HaikuVM for you in nativeCFunctions.cpp
      //////////////////Start of user code given per Java class by cImpl
      #include <LedControl.h>
      typedef struct avr_gallerie_user_bachiander_LedControl {
        jobject    cobject; //Ljava/lang/Object;
      } avr_gallerie_user_bachiander_LedControl;
      //////////////////End   of user code given per Java class by cImpl
      ...
      JNIEXPORT void Java_avr_gallerie_user_bachiander_LedControl_setLed
        (JNIEnv *env, jobject obj, jint arg1, jint arg2, jint arg3, jboolean arg4)
      {
      //////////////////Start of user code given by cImpl
      #define cls avr_gallerie_user_bachiander_LedControl
      jfieldID fid = (*env)->GetFieldID(env, cls, cobject, "Ljava/lang/Object;");
      if (fid == 0)
          return;
      LedControl* cobj = (LedControl*) ((*env)->GetObjectField(env, obj, fid));
      cobj -> setLed(arg1, arg2, arg3, arg4);
      //////////////////End   of user code given by cImpl
      }
      

      1.7) At least this is the path. For now, many things go wrong on this way. At the end things should go smoother with the usage of (future) @NativeCppMethod.

      2)

      Where need the .h/.cpp files to be placed to get picked up?

      For an answer see: http://haiku-vm.sourceforge.net/#[[JNI%20enhanced]]
      Short answer: anywhere in your myCProject folder OR In the same folder as your main java (So you are on the right track).

      From this I guess, your message "multiple definitions found" emits from the fact that file "LiquidCrystal.cpp" is two times somewhere in your myCProject directory.

      3)
      In you C code I found some undefined things like:
      pinMode(..)
      spiTransfer(..)
      or even #include <arduino.h>
      From this I guess you want to step and compile against the Arduino library by using the Arduino IDE. This can be done with HaikuVM by using the configuration arduinoIDEUpload and haikufying like this:</arduino.h>

      cd <YourArduinoIDEHOME>/libraries
      /../haikuVM/bin/haiku -v --Config arduinoIDEUpload /../projects/src/LEDMatrix/$LEDMatrix.java
      

      4)
      Maybe this thread is of some help for you:
      https://sourceforge.net/p/haiku-vm/discussion/general/thread/25b657d8/

      Kind regards
      Bob Genom

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.