2013-04-05 83 views
1

我正在嘗試使用JNI來調用c中定義的函數。這真的很奇怪,因爲當我運行我的Java程序時,有時我會遇到一個錯誤,而其他時候我會得到一個錯誤。在這裏,他們是:具有使用gsl的C函數的Java JNI。

 82 [main] java (5556) C:\Windows\system32\java.exe: *** fatal error - cygheap base mismatch detected - 0x612708F0/0x17FF08F0. 
This problem is probably due to using incompatible versions of the cygwin DLL. 
Search for cygwin1.dll using the Windows Start->Find/Search facility 
and delete all but the most recent version. The most recent version *should* 
reside in x:\cygwin\bin, where 'x' is the drive on which you have 
installed the cygwin distribution. Rebooting is also suggested if you 
are unable to find another cygwin DLL. 
java.lang.UnsatisfiedLinkError: C:\cygwin\home\Juli▒n\Pruebas_JNI\Caracterizacion.dll: Se realiz▒ un acceso no v▒lido a la ubicaci▒n de memoria 
     at java.lang.ClassLoader$NativeLibrary.load(Native Method) 
     at java.lang.ClassLoader.loadLibrary1(Unknown Source) 
     at java.lang.ClassLoader.loadLibrary0(Unknown Source) 
     at java.lang.ClassLoader.loadLibrary(Unknown Source) 
     at java.lang.Runtime.loadLibrary0(Unknown Source) 
     at java.lang.System.loadLibrary(Unknown Source) 
     at Main.<clinit>(Main.java:6) 
Exception in thread "main" 

Exception in thread "main" java.lang.UnsatisfiedLinkError: Main.caracterizar()[F 
     at Main.caracterizar(Native Method) 
     at Main.main(Main.java:10) 

我想我所做的一切都是正確的,甚至認爲它似乎我沒有。

這裏是我的C函數

/* 
* File: main.c 
* Author: OCARDONAM 
* Created on 14 de enero de 2013, 11:46 AM 
*/ 
#include <stdio.h> 
#include <math.h> 
#include <string.h> 
#include <jni.h> 
#include <gsl/gsl_vector.h> 
#include <gsl/gsl_statistics.h> 
#include <gsl/gsl_blas.h> 
#include <gsl/gsl_linalg.h> 
#include "sizedata.h" 
#include "elementary_math_vec.h" 
#include "contar.h" 
#include "media.h" 
#include "Main.h" 


JNIEXPORT jfloatArray JNICALL Java_Main_caracterizar (JNIEnv *env, jclass class) { 
    //variables 
    int n_fil, n1, n2, i; 
    char *filename; 
    //features names 
    double m,T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11;//,F1,F2,F3,F4,F5,F6,F7,F8,F9,F10,F11; 
    //load signal and define its size 
    filename = "reg_test.txt"; 
    tamano(filename, &n1, &n2); 
    n_fil = n1-2; 

    gsl_vector * v = gsl_vector_alloc (n_fil); 
    { 
     FILE * f = fopen (filename, "r"); 
     gsl_vector_fscanf (f, v); 
     fclose (f); 
    } 


    // statistics features in time domain 
    double data[n_fil],tmp[n_fil]; 
    for (i = 0; i < n_fil; i++) 
    { 
     data[i] = gsl_vector_get(v,i); 
    } 

    //centered data 
    m = gsl_stats_mean(data, 1, n_fil); 
    for (i = 0; i < n_fil; i++) { 
     data[i] = data[i]-m; 
     gsl_vector_set(v,i,data[i]); 
    } 
    T1 = gsl_stats_mean(data, 1, n_fil); //mean 
    T2 = gsl_stats_sd_m(data, 1, n_fil, T1); //standard deviation  
    T3 = gsl_blas_dnrm2(v)/sqrt(n_fil);//RMS 
    T4 = gsl_stats_skew(data, 1, n_fil); //skewness  
    T5 = gsl_stats_kurtosis(data, 1, n_fil) + 3; //kurtosis 
    T6 = ch_T6(data,n_fil); 
    T7 = ch_T7(data,n_fil); //absolute maximum 
    T8 = T7/T3; //Crest Factor 
    T9 = T7/T6; 
    T10 = ch_T10(data,n_fil,T3);//Shape Factor 
    T11 = ch_T11(data,n_fil,T7); 


    //print a vector 

    jfloat res[1000]; 
    jfloatArray jres; 

    for (i = 0; i < n1-2; i++) { 
     res[i] = (jfloat) gsl_vector_get(v, i); 
    } 
    gsl_vector_free (v); 

    (*env)->SetFloatArrayRegion(env, jres, 0, n1-2, res); 
    return jres; 
} 

這裏是Java代碼我用它來調用它:

public class Main { 

    public native float[] caracterizar(); 

    static { 
     System.loadLibrary("Caracterizacion"); 
    } 

    public static void main(String args[]) { 
     float ans[] = (new Main()).caracterizar(); 

     for (int i=0 ; i<ans.length ; i++) 
      System.out.println(ans[i]); 
    } 
} 

而且,這裏是我用來編譯和鏈接C程序:

gcc -D__int64="long long" -c -I/cygdrive/c/Program\ Files/Java/jdk1.7.0_11/include/ -I/cygdrive/c/Program\ Files/Java/jdk1.7.0_11/include/win32/ -o Main.o Main.c 

鏈接:

gcc -shared -L/usr/local/lib -o Caracterizacion.dll Main.o -lgsl -lgslcblas -lm 

我不知道錯誤在哪裏。我測試了其他的JNI程序,它們工作正常,所以我認爲問題在於我包含gsl庫的方式。

我希望你能幫助我。謝謝

+0

你有沒有試過在Linux上運行這個? – stdcall 2013-04-09 19:50:54

+0

不,我沒有。你認爲這可能是問題嗎? – 2013-04-09 20:42:34

+0

從錯誤,它看起來像是一個環境錯誤,而不是編碼錯誤,我建議你測試它在不同的環境,如Linux,其中gcc是系統原生的... – stdcall 2013-04-09 20:46:21

回答

1

我的猜測是你的gsl庫可能被編譯並鏈接到不同版本的cygwin。而你的main.c代碼是用你當前版本的cygwin編譯的,有衝突。你可以試試這些:

  1. 使用當前的cygwin環境重建你的gsl。
  2. 鏈接到gsl的靜態庫。
  3. 使用msvc,可以在msvc上編譯gsl,我有visual studio solution,你可以製作靜態庫或動態庫。
3

不要使用cygwin GCC,除非你真的想把你的程序鏈接到cygwin庫。如果你需要它,你還必須將cygwin dll打包到你的包中。

如果你希望它在Windows上運行,使用mingw編譯器(也有Cygwin的包,但它會創建cygwin無關的二進制文件)或MSVC項目。除非Java啓用了cygwin,否則它不會理解cygwin路徑,但是你的本地代碼將會。這將變得非常混亂。除非你知道你需要它,否則使用cygwin來編寫腳本,但是使用mingw-gcc作爲編譯器來編譯二進制文件或使用Min Lin的工作室項目。