Я пытаюсь использовать JNI для вызова функции, определенной в c. Это действительно странно, потому что когда я запускаю свою Java-программу, иногда я получаю одну ошибку, а иногда — другую. Вот они:
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.
Я надеюсь, что вы можете мне помочь. Спасибо
Не используйте cygwin GCC, если вы действительно не хотите, чтобы ваша программа была связана с библиотеками cygwin. Если вам это нужно, вы должны также упаковать cygwin dll в ваш пакет.
Если вы хотите, чтобы он работал в Windows, используйте компилятор mingw (также есть пакет для Cygwin, но он создаст независимый от Cygwin двоичный файл.) Или проект MSVC. Если Java не поддерживает Cygwin, он не будет понимать пути Cygwin, но ваш нативный код будет. Это станет действительно запутанным. Если вы не знаете, что вам это нужно, используйте cygwin для создания сценариев, но используйте mingw-gcc в качестве компилятора для создания двоичных файлов или используйте студийный проект Min Lin.
Я предполагаю, что ваша библиотека gsl может быть скомпилирована и связана с другой версией cygwin. И ваш код main.c скомпилирован с вашей текущей версией Cygwin, есть конфликт. Вы можете попробовать это: