Привязки JNI - неопределенный символ: gcj_personality_v0 - PullRequest
2 голосов
/ 27 февраля 2011

Я пытаюсь преобразовать действительную привязку C JNI в C ++, потому что хочу связать с исходным кодом C ++ (реализация алгоритма обработки изображений с открытым исходным кодом) из некоторого кода Java.У меня все работает в C, включая класс Java, версию C привязки JNI и систему сборки, и исключает с использованием источника C ++.

Я сейчас пытаюсь преобразоватьПривязка JNI к C ++, так что я могу добавить исходный код C ++ в систему сборки и вызвать его из привязки, но я использую неопределенный символ.

Мой Makefile довольно прост:

GCC = gcc -Wall -g -std=gnu99
CXX = g++ -Wall -g
LIBOBJS = parallelsurf_jni.o

LIB=libparallelsurf.so
DESTLIB=../../lib/$(LIB)

all: $(DESTLIB)


$(DESTLIB): $(LIB)
    cp $(LIB) $(DESTLIB)

libparallelsurf.so: parallelsurf_ParallelSURF.h $(LIBOBJS)
    ld --shared $(LIBOBJS) -o libparallelsurf.so 

parallelsurf_ParallelSURF.h:
    echo "Rebuilding JNI headers. Ensure java file has been recently built."
    javah -classpath ../../parallelsurf.jar -jni parallelsurf.ParallelSURF

clean:
    rm -f $(LIBOBJS) *~ parallelsurf_ParallelSURF.h $(LIB) $(DESTLIB) $(LIBOBJS)

JNI_INCLUDES = -I/usr/lib/jvm/java-6-sun/include/ -I/usr/lib/jvm/java-6-sun/include/linux -I/usr/lib/jvm/java-6-openjdk/include/

%.o: %.cpp
    $(CXX) -shared -O2 -c -fPIC -fno-omit-frame-pointer -fno-stack-protector -D_REENTRANT $< $(JNI_INCLUDES)

Таким образом, мой заголовочный файл автоматически генерируется с javah, и я, похоже, не искажал его при копировании с .h в .cpp.У меня нет extern "C" блоков в файле .cpp, как указано в этом посте .

Я также включил прагму в соответствии с этим постом: Неопределенный символ _gxx_personality_v0 вссылка .Прагма: #pragma GCC java_exceptions

Теперь этот неопределенный символ (gxx_personality), кажется, хорошо упоминается / документируется в Интернете.Ряд сообщений указывают на этот комментарий о C ++ / Java обработке исключений , которая предлагает использовать эту прагму.Тем не менее, после включения этой прагмы, я получаю еще один неопределенный символ, который плохо покрыт (я получаю ровно 1 попадание Google): _gcj_personality_v0

Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/chardson/chardson/parallelsurf/lib/libparallelsurf.so: /home/chardson/chardson/parallelsurf/lib/libparallelsurf.so: undefined symbol: __gcj_personality_v0
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1750)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1675)
    at java.lang.Runtime.loadLibrary0(Runtime.java:840)
    at java.lang.System.loadLibrary(System.java:1047)
    at parallelsurf.ParallelSURF.<clinit>(ParallelSURF.java:17)
    at testpsurf.<init>(testpsurf.java:11)
    at testpsurf.main(testpsurf.java:23)

Я не уверен, что делать с этим неопределенным символоми я понятия не имею, куда еще обратиться.Возможно, в моем коде JNI есть просто ошибка, которую можно исправить, чтобы избавиться от этой проблемы?Мой код JNI C ++ включен ниже для полноты.

#include <jni.h>
#include <stdio.h>
#include <assert.h>

#pragma GCC java_exceptions

/*
 * Class:     parallelsurf_ParallelSURF
 * Method:    parallelsurf_get_keypoints
 * Signature: (II[FZ)Ljava/util/ArrayList;
 */
JNIEXPORT jobject JNICALL Java_parallelsurf_ParallelSURF_parallelsurf_1get_1keypoints
  (JNIEnv *jenv, jclass jcls, jint width, jint height, jfloatArray gray, jboolean rotInvariant)
{
    // init arraylist class
    jclass arrayListClass = jenv->FindClass("java/util/ArrayList");
    assert(arrayListClass != NULL);

    jmethodID alInitMethodId = jenv->GetMethodID(arrayListClass, "<init>", "()V");
    assert(alInitMethodId != NULL);

    jobject arrayList = jenv->NewObject(arrayListClass, alInitMethodId);

    jmethodID alAddMethodId = jenv->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
    assert(alAddMethodId != NULL);

    // init keypoint class
    jclass keypointClass = jenv->FindClass("parallelsurf/Keypoint");
    assert(keypointClass != NULL);

    jmethodID kpInitMethodId = jenv->GetMethodID(keypointClass, "<init>", "(DDDDID[D)V");
    assert(kpInitMethodId != NULL);

    jdoubleArray descriptor = jenv->NewDoubleArray(10);
    assert(descriptor != NULL);

    jdouble vals[10];
    for (int i=0; i < 10; i++) {
        vals[i] = (jdouble) i;
    }

    jenv->SetDoubleArrayRegion(descriptor, 0, 10, vals);

    // create keypoint
    jobject kp = jenv->NewObject(keypointClass, kpInitMethodId,
                                    (jdouble) 1, (jdouble) 2, (jdouble) 3,
                                    (jdouble) 4, (jint) 5, (jdouble) 6,
                                    descriptor);

    // add to arraylist
    jenv->CallBooleanMethod(arrayList, alAddMethodId, kp);
    jenv->DeleteLocalRef(kp);

    return arrayList;
}

Спасибо за внимание.Ваша помощь очень ценится.

1 Ответ

0 голосов
/ 28 февраля 2011

Какой-то замечательный джентльмен из списка рассылки gcc-help понял это:

  • Вместо #pragma GCC java_exceptions, чтобы справиться с __gxx_personality_v0, сделайте ссылку ld в -l gcc_s
  • Если __gcj_personality_v0 не определено, сделайте ld ссылку в -l gcj
  • Имеете ld ссылку -l stdc++
  • Убедитесь, что у вас есть libstdc ++, libgcjX-dev (X - версия) и libgcc на вашем компьютере

Если вы связываетесь с g ++ (я не), некоторые из них могут произойти автоматически (stdc ++?)

Кроме того, убедитесь, что выне забудьте (или не потеряете) строку #import для заголовка JNI - вам понадобятся extern C {} биты, или вы получите UnsatisfiedLinkError

...