Question

I have a robot called the "Robotic Arm Edge" and the USB Interface. I am trying to make custom software, but this involves the Java Native Interface. I chose Java because it is much easier to make a gui interface in than the ATK+ library for C/C++. The reason I need the Java Native interface is libusb, which I already have a working controller for that I wrote myself. Now, all that I need to do is write a Java wrapper, but I need to convert a jstring to a c string. The GetStringUTFChars JNI method always results in a fatal error, and I have tried almost every variation of the method possible. This is the Java class:

RoboController.java:

package arm.robot;

import arm.robot.enums.*;


public class RoboController {


    static {
        System.loadLibrary("robojava");
        sendToRobo0("");
    }

    static Pinchers m1 = Pinchers.stopped;
    static Joint    m2 = Joint.stopped;
    static Joint    m3 = Joint.stopped;
    static Joint    m4 = Joint.stopped;
    static Base     m5 = Base.stopped;
    static Light    l  = Light.off;

    private static native boolean sendToRobo0(String cmds);

    public static void sendToRobo(){
        StringBuilder sb = new StringBuilder("");
        boolean first = true;

        if(m1.equals(Pinchers.opening)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m1o");
        }
        else if(m1.equals(Pinchers.closing)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m1c");
        }

        if(m2.equals(Joint.up)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m2u");
        }
        else if(m2.equals(Joint.down)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m2d");
        }

        if(m3.equals(Joint.up)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m3u");
        }
        else if(m3.equals(Joint.down)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m3d");
        }

        if(m4.equals(Joint.up)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m4u");
        }
        else if(m4.equals(Joint.down)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m4d");
        }

        if(m5.equals(Base.clockwise)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m5cw");
        }
        else if(m5.equals(Base.counterclockwise)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("m5ccw");
        }

        if(l.equals(Light.on)) {
            if(!first){
                sb.append(" ");
            }
            else first = false;
            sb.append("lon");
        }
        sendToRobo0(sb.toString());
    }
}

The header from javah:

arm_robot_RoboController.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class arm_robot_RoboController */

#ifndef _Included_arm_robot_RoboController
#define _Included_arm_robot_RoboController
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     arm_robot_RoboController
 * Method:    sendToRobo0
 * Signature: (Ljava/lang/String;)Z
 */
JNIEXPORT jboolean JNICALL Java_arm_robot_RoboController_sendToRobo0
  (JNIEnv *, jclass, jstring);

#ifdef __cplusplus
}
#endif
#endif

And finally, the implementation, where the fatal error occurs:

arm_robot_RoboController.cpp

#include <jni.h>
#include <string>
#include <iostream>
#include "arm_robot_RoboController.h"

using namespace std;


JNIEXPORT jboolean JNICALL Java_arm_robot_RoboController_sendToRobo0(JNIEnv* env, jclass c, jstring args){
    const char *str= env->GetStringUTFChars(args,(jboolean*)0); //FATAL ERROR HERE
    //string s(str);
    //cout << s;
    return true;
}

Error log:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0xb676a978, pid=2912, tid=2842113136
#
# JRE version: Java(TM) SE Runtime Environment (7.0_40-b43) (build 1.7.0_40-b43)
# Java VM: Java HotSpot(TM) Client VM (24.0-b56 mixed mode linux-arm )
# Problematic frame:
# V  [libjvm.so+0x262978]  jni_GetStringUTFChars+0x74
#
# Core dump written. Default location: /home/pi/robotic arm/gui/core or core.2912
#
# An error report file with more information is saved as:
# /home/pi/robotic arm/gui/hs_err_pid2912.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.sun.com/bugreport/crash.jsp
#
Aborted (core dumped)

The build command line I use:

g++ -c -I"/usr/lib/jvm/jdk-7-oracle-armhf/include" -I"/usr/lib/jvm/jdk-7-oracle-armhf/include/linux" robo.cpp
g++ -I"/usr/lib/jvm/jdk-7-oracle-armhf/include" -I"/usr/lib/jvm/jdk-7-oracle-armhf/include/linux" -olibrobojava.so -shared -Wl,-soname,robojava.so arm_robot_RoboController.cpp robo.o

I am using a Raspberry Pi Model B running close to the latest Raspbian Wheezy. I cannot fing out what I am doing wrong.

Was it helpful?

Solution

As in EJP comment my previous suggestion that its caused by missing &isCopy was wrong, Iam leaving only ReleaseStringUTFChars part. I can only suggest adding logging before and after suspiciously looking calls, also you should look into logcat, android sometimes outputs there hints when something wrong happens with jni in native code.


Also you must call:

ReleaseStringUTFChars

after using str

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top