JNI в С++ для чтения файла в jbyteArray

Я пишу программу на С++ в UNIX для создания общей библиотеки, которая будет вызываться в java с использованием JNI. Эта программа C++ должна прочитать файл в поле UNIX, затем его нужно будет преобразовать в jbyteArray (тип данных JNI), чтобы JAVA могла его использовать.

Я прочитал файл на C++ в char*, но не смог преобразовать в jbyteArray. Пожалуйста, помогите.

Код ниже::

#include <iostream>
#include <fstream>
#include <stdio.h>
#include "com_sp_dll_NativeMethods.h"   // this header file was generated by java

using namespace std;

JNIEXPORT void JNICALL Java_HelloWorld_displayMessage(JNIEnv *env, jobject obj)
{
    printf("Hello World!\n");
}

JNIEXPORT jbyteArray JNICALL Java_com_sp_dll_NativeMethods_getFile(JNIEnv *env, jobject obj)
{
    ifstream fl("/home/rkannan/myFile.txt");
    fl.seekg(0, ios::end );
    size_t len = fl.tellg();
    char *ret = new char[len];
    fl.seekg(0, ios::beg);
    fl.read(ret, len);
    fl.close();

    int i = 0;
    jbyte *a1 = null;

    while(ret[i] != '\0'){
        cout<<ret[i];
        al[i] = ret[i];
        i++;
    }

    jbyteArray result = env->NewByteArray( len);
    env->SetByteArrayRegion( result, 0, len, (const jbyte*) ret );
    delete[] ret;
    return result;
  }

Ошибка заключается в следующем

bash-3.00$ g++ -I /usr/jdk/instances/jdk1.5.0/include -I /usr/jdk/instances/jdk1.5.0/include/solaris -o libSample.so -shared com_sp_dll_NativeMethods.cpp
        Text relocation remains                         referenced
            against symbol                  offset      in file
        std::__ioinit                       0x550       /var/tmp//ccKCiEKq.o
        std::__ioinit                       0x554       /var/tmp//ccKCiEKq.o
        std::__ioinit                       0x588       /var/tmp//ccKCiEKq.o
        std::__ioinit                       0x58c       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x204       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x208       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x244       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x248       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x2f4       /var/tmp//ccKCiEKq.o
        .rodata (section)                   0x2f8       /var/tmp//ccKCiEKq.o
        std::fpos<__mbstate_t>::operator long long() const0x348         /var/tmp//ccKCiEKq.o
        std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char)0x400             /var/tmp//ccKCiEKq.o
        std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)0x2cc      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::is_open()0x260      /var/tmp//ccKCiEKq.o
        std::basic_istream<char, std::char_traits<char> >::read(char*, int)0x39c        /var/tmp//ccKCiEKq.o
        JNIEnv_::SetByteArrayRegion(_jbyteArray*, int, int, signed char const*)0x468            /var/tmp//ccKCiEKq.o
        operator new[](unsigned int)        0x364       /var/tmp//ccKCiEKq.o
        std::basic_istream<char, std::char_traits<char> >::seekg(long long, std::_Ios_Seekdir)0x31c             /var/tmp//ccKCiEKq.o
        std::basic_istream<char, std::char_traits<char> >::seekg(long long, std::_Ios_Seekdir)0x384             /var/tmp//ccKCiEKq.o
        std::basic_istream<char, std::char_traits<char> >& std::operator>><char, std::char_traits<char> >(std::basic_istream<char, std::char_traits<char> >&, char*)0x2b4       /var/tmp//ccKCiEKq.o
        printf                              0x20c       /var/tmp//ccKCiEKq.o
        JNIEnv_::NewByteArray(int)          0x444       /var/tmp//ccKCiEKq.o
        std::ios_base::Init::Init()         0x558       /var/tmp//ccKCiEKq.o
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::size() const0x14        /var/tmp//ccKCiEKq.o
        std::cout                           0x2c0       /var/tmp//ccKCiEKq.o
        std::cout                           0x2c4       /var/tmp//ccKCiEKq.o
        std::cout                           0x3f4       /var/tmp//ccKCiEKq.o
        std::cout                           0x3f8       /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream()0x234       /var/tmp//ccKCiEKq.o
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator[](unsigned int) const0x9c              /var/tmp//ccKCiEKq.o
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator[](unsigned int) const0x128             /var/tmp//ccKCiEKq.o
        std::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator[](unsigned int) const0x184             /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::open(char const*, std::_Ios_Openmode)0x250          /var/tmp//ccKCiEKq.o
        std::ios_base::Init::~Init()        0x590       /var/tmp//ccKCiEKq.o
        std::basic_ios<char, std::char_traits<char> >::eof() const0x288         /var/tmp//ccKCiEKq.o
        unsigned int const& std::min<unsigned int>(unsigned int const&, unsigned int const&)0x44        /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()0x49c      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()0x4ac      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()0x4d4      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::~basic_ifstream()0x4f8      /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::close()0x2e4        /var/tmp//ccKCiEKq.o
        std::basic_ifstream<char, std::char_traits<char> >::close()0x3ac        /var/tmp//ccKCiEKq.o
           std::basic_ifstream<char, std::char_traits<char> >::basic_ifstream(char const*,     std::_Ios_Openmode)0x300        /var/tmp//ccKCiEKq.o
            operator delete[](void*)            0x484       /var/tmp//ccKCiEKq.o
           std::basic_istream<char, std::char_traits<char> >::tellg()       0x334         /var/tmp//ccKCiEKq.o
            _Unwind_Resume                      0x508       /var/tmp//ccKCiEKq.o
            ld: fatal: relocations remain against allocatable but non-writable sections
            collect2: ld returned 1 exit status

person Renga    schedule 12.10.2012    source источник
comment
возможный дубликат JNI: передача байтов из c++ в java   -  person mkaes    schedule 12.10.2012
comment
Возможно, вы захотите попробовать это снова с помощью JavaCPP, IMO намного проще работать, чем необработанный JNI.   -  person Samuel Audet    schedule 13.10.2012
comment
Почему? Все это можно сделать на Java. Нет ничего, что можно было бы получить. Не то, чтобы вы должны читать целые файлы в память в первую очередь.   -  person user207421    schedule 17.10.2012


Ответы (1)


Похоже, вы не устанавливаете какие-либо байтовые данные в массив. На самом деле, поскольку jbyte типизирован для char, вы можете напрямую установить свой массив char в setByteArrayRegion следующим образом:

env->SetByteArrayRegion( result, 0, 100, ret );

Изменить: Кроме того, предполагая, что al[i] должен быть a1[i], вы делаете что-то очень опасное, поскольку не выделяете место для a1. По сути, выполнение того, что я предлагаю выше, означает, что вы можете избавиться от всего этого цикла. Также не забудьте удалить массив C++, когда закончите с ним (т.е. скопируете его в jByteArray)!

JNIEXPORT jbyteArray JNICALL Java_com_sp_dll_NativeMethods_getFile
       (JNIEnv *env, jobject obj)
{
        ifstream fl("/home/rkannan/myFile.txt");
        fl.seekg(0, ios::end );
        size_t len = fl.tellg();
        char *ret = new char[len];
        fl.seekg(0, ios::beg);
        fl.read(ret, len);
        fl.close();

        jbyteArray result = env->NewByteArray( len);
        env->SetByteArrayRegion( result, 0, len, (const jbyte*)ret );

        delete[] ret;

        return result;
}
person Goz    schedule 12.10.2012
comment
+1; Я бы также предложил использовать переменную len при создании и настройке массива байтов вместо фиксированного значения 100. - person maba; 12.10.2012
comment
Вы можете использовать std::string или std::vector‹char› в качестве временного контейнера. - person MadScientist; 12.10.2012
comment
Спасибо, Гоз и другие. ошибка: неверное преобразование из char*' to const jbyte*' com_sp_dll_NativeMethods.cpp:: ошибка: инициализация аргумента 4 `void - person Renga; 12.10.2012
comment
Я получил вышеупомянутую ошибку. Извините, что вредитель. Я не знаком с типами данных C++ и JNI. - person Renga; 12.10.2012
comment
@Renga: Тогда отредактируйте исходный вопрос и опубликуйте ошибки. - person Goz; 12.10.2012
comment
@Renga: то, что вы получаете, является ошибкой компоновщика. Вы уверены, что включили все необходимые библиотеки? - person Goz; 12.10.2012
comment
@Goz: Пожалуйста, дайте мне знать, как включить библиотеки. Я не использую какие-либо конкретные библиотеки. Есть ли что-нибудь, что мне нужно добавить? Мне очень нужна твоя помощь. - person Renga; 12.10.2012
comment
@Renga: я ничего не знаю о вашем процессе сборки. Но вы используете библиотеки, например, JNI и STL. Покажи мне, как ты строишь, и я смогу помочь. - person Goz; 12.10.2012
comment
@Goz: Могу я узнать ваш адрес электронной почты? Я могу отправить вам файлы по почте. - person Renga; 12.10.2012
comment
@Renga: Все, что мне нужно, это ваши командные строки GCC и LD ... или, возможно, ваш make-файл. - person Goz; 12.10.2012
comment
g++ -I /usr/jdk/instances/jdk1.5.0/include -I /usr/jdk/instances/jdk1.5.0/include/solaris -o libSample.so -shared com_sp_dll_NativeMethods.cpp Это то, о чем вы упомянули? - person Renga; 12.10.2012
comment
@Renga Вы не должны спрашивать электронную почту людей. Идея SO заключается в том, что все является общедоступным. Если кто-то найдет ответ здесь полезным, то было бы нехорошо, если бы какая-то его часть оказалась в чьем-то почтовом ящике. Вместо этого используйте функцию чата. Он сохраняет все разговоры. - person maba; 12.10.2012
comment
@Renga: TBH, я не совсем уверен, что с этим не так. Вы можете создать новый вопрос, в котором конкретно задается вопрос о том, как скомпилировать и связать код JNI. Вы, вероятно, получите лучший ответ, чем спрашивать в комментариях здесь... - person Goz; 12.10.2012
comment
@Goz: Большое спасибо за вашу помощь. Кмаба: Прошу прощения. Я новичок на этом форуме. Я не буду делать это снова. Еще раз спасибо. - person Renga; 12.10.2012