2016-07-21 55 views
0

我正在处理一些本地代码以将RPI感应帽与我的java东西进行接口,而且我无法让我的本机意味着。我已经在java中编写了存根,编译它然后使用javah来提取头文件。我创建了C中的方法来将一个简单的char数组转换为一个字符串来返回。我似乎无法得到它编译。 的Java:无法编译JNI C不兼容的指针类型

/** 
* NativeTest - PACKAGE_NAME 
* Created by matthew on 21/07/16. 
*/ 
class SenseHat 
{ 
    static { 
     System.loadLibrary("SenseHat"); 
    } 

    public native String getTemperature(); 
    public native String getHumidity(); 
    public native String getOrientation(); 

} 

头文件

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

#ifndef _Included_SenseHat 
#define _Included_SenseHat 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  SenseHat 
* Method: getTemperature 
* Signature:()Ljava/lang/String; 
*/ 
JNIEXPORT jstring JNICALL Java_SenseHat_getTemperature 
    (JNIEnv *, jobject); 

/* 
* Class:  SenseHat 
* Method: getHumidity 
* Signature:()Ljava/lang/String; 
*/ 
JNIEXPORT jstring JNICALL Java_SenseHat_getHumidity 
    (JNIEnv *, jobject); 

/* 
* Class:  SenseHat 
* Method: getOrientation 
* Signature:()Ljava/lang/String; 
*/ 
JNIEXPORT jstring JNICALL Java_SenseHat_getOrientation 
    (JNIEnv *, jobject); 

#ifdef __cplusplus 
} 
#endif 
#endif 

C文件:

#include <jni.h> 
#include <stdio.h> 
#include "SenseHat.h" 

JNIEXPORT jstring JNICALL Java_SenseHat_getTemperature(JNIEnv *env, jobject thisObj) { 
    char done[] = "temperature"; 
    jstring answer; 
    /* Make a new String based on done, then free done. */ 
    answer = (*env)->NewStringUTF(env,&done); 
    free(done); 
    return answer; 

} 

JNIEXPORT jstring JNICALL Java_SenseHat_getHumidity(JNIEnv *env, jobject thisObj) { 
    char done[9] = "humidity"; 
    jstring answer; 
    /* Make a new String based on done, then free done. */ 
    answer = (*env)->NewStringUTF(env,&done); 
    free(done); 
    return answer; 

} 

JNIEXPORT jstring JNICALL Java_SenseHat_getOrientation(JNIEnv *env, jobject thisObj) { 
    char done[12] = "orientation"; 
    jstring answer; 
    /* Make a new String based on done, then free done. */ 
    answer = (*env)->NewStringUTF(env,&done); 
    free(done); 
    return answer; 
} 

我使用下面的命令编译它:

gcc -I /usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include/ -I /usr/lib/jvm/jdk-8-oracle-arm32-vfp-hflt/include/linux/ -shared -o libSenseHat.so SenseHat.c 
+1

你能提供编译器输出吗? – Sergio

回答

1

你可以用” t do

char done[] = "temperature"; 
    /* ... */ 
    answer = (*env)->NewStringUTF(env,&done); 
           /* --^-- & is redundant */ 

应该

char done[] = "temperature"; 
    /* ... */ 
    answer = (*env)->NewStringUTF(env,done); 

甚至

answer = (*env)->NewStringUTF(env,"temperature"); 

还你不应该free(done)。此内存未分配到malloc(),因此释放会导致未定义的行为。

+0

干得好极了。 :D – MAWood

+0

*你不能这样做......'NewStringUTF(env,&done);'*不正确,'array'和'&array'都是正确的,它们都计算到'array'的第一个元素的地址。编写一些能够发出'array'和'&array'结果的代码,例如'printf(“%p \ n%p \ n”,done,&done);'',这两个地址是相同的。在这个问题中发布的代码是'free(done)'行。 –

+0

@AndrewHenle无论指针指向相同的内存位置,它们都有完全不同的类型,'done'是'char *','&done'是'char(*)[]'。函数有下一个原型'jstring NewStringUTF(JNIEnv * env,const char * bytes);'so'&done'是不可接受的参数,编译器告诉它。 – Sergio

1

我看到的第一个问题是:声明本地数组变量并在它们上使用free()。可以使用malloc()/ free()或者在本地声明你的数组,但不要混合使用两者。