Используйте функцию C ++ в Java - PullRequest
1 голос
/ 05 августа 2011

У меня есть проект C ++ с некоторыми файлами .cpp и .h.Один из этих .cpp имеет функцию с такой подписью:

int** verts(int L, int W, int l, int w)

Я хотел бы использовать эту функцию в проекте Java.Да, я мог бы переписать его на Java, но это очень очень четко сформулированная функция.Было бы здорово вызвать эту функцию (и получить матрицу целых чисел) из Java.

Любая идея?
Пожалуйста, примите во внимание, что я программист на Java, я очень неопытен в C ++: P

Ответы [ 2 ]

2 голосов
/ 05 августа 2011

Вы можете написать библиотеку, которая содержит эту функцию, и обернуть ее Оболочка JNI, но это не тривиально. Самый важный вопрос что на самом деле представляют int** и как ими управляют: и как вы должны удалить их, и как вы хотите представить их в Java. Просто догадываясь, я подозреваю, что указатель указывает на массив int*, каждый из которых указывает на массив int; это обычное дело представление для двумерного массива в C (но не то, что мы обычно используют в C ++). Что касается того, как и как их удалить, это должны быть задокументированы библиотекой, которая определяет verts. При условии, сначала вам нужно объявить функцию как нативную в классе Java:

class Verts
{
    static {
        System.loadLibrary( "<i>libraryName</i>" );
    }

    private static Integer[] nativeVerts( int L, int W, int l, int w );
    public Integer[][] verts( int L, int W, int l, int w )
    {
        Integer[] tmp = nativeVerts( L, W, l, w );
        //  reshape tmp...
        return reshapedData;
    }
}

(Я предпочел вернуть уплощенный одномерный массив, а не чем Integer[][]. Это сделает C ++ намного проще.)

что вам нужно сделать, это написать функцию в следующих строках:

#include "jni.h"
extern "C" JNIEXPORT jIntArray JNICALL Java_Verts_nativeVerts(
    JNIEnv* env,
    jclass,
    jint L,
    jint W,
    jint l,
    jint w)
{
    int** results = verts( L, W, l, w );
    std::vector<int> tmp;
    //  Fill tmp with the flattened results.
    //  Then do whatever you have to do to clean up the int**.
    jintArray jResults = env->newIntArray( tmp.size() );
    env->SetIntArrayRegion( jResults, 0, tmp.size(), &tmp[0] );
    return jResults;
}

За исключением того, что вышеперечисленное также требует значительно большей проверки ошибок.

Наконец, скомпилируйте и свяжите вышесказанное в dll с именем, которое вы дали System.loadLibrary() функция на стороне Java. И убедитесь, что ваша среда настроена так, что Java может найти DLL (либо через $ LD_LIBRARY_PATH (Unix) или% path% (Windows) или путем передачи пути по означает -Djava.library.path=... в командной строке Java).

1 голос
/ 05 августа 2011

Вы не сможете использовать эту функцию напрямую (или, если вы это сделаете, у вас будет утечка памяти, поскольку Java не может знать, как освободить память, выделенную и возвращенную verts).Вы должны быть в состоянии написать простую оболочку, которая следует правилам JNI.

При вызовах между языками вам действительно нужно использовать буферы, предоставляемые вызывающей стороной.Для этой функции вашей оболочке нужно будет скопировать результаты в предоставленный вызывающим буфер, а затем использовать соответствующую функцию C ++, чтобы освободить память, возвращаемую verts.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...