3

I am writing a C++ program in UNIX to generate a shared library which will be called in java using JNI. This C++ program has to read a file in UNIX box then it will have to be converted into jbyteArray (JNI data type) so that JAVA can use it.

I read the file in C++ into char* but could not convert into jbyteArray. Please help it.

Code is below::

#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;
  }

The error is as follows

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
artyom.stv
  • 2,097
  • 1
  • 24
  • 42
Renga
  • 119
  • 1
  • 3
  • 12
  • possible duplicate of [JNI: passing bytes from c++ to java](http://stackoverflow.com/questions/6246915/jni-passing-bytes-from-c-to-java) – mkaes Oct 12 '12 at 07:45
  • You might want to try that again with [JavaCPP](http://code.google.com/p/javacpp/), it's IMO much easier get working than raw JNI – Samuel Audet Oct 13 '12 at 07:03
  • Why? You can do all this in Java. There is nothing to be gained. Not that you should be reading entire files into memory in the first place. – user207421 Oct 17 '12 at 00:53

1 Answers1

4

You don't appear to be setting any byte data to the array. In fact as a jbyte is typedef'd to a char you can directly set your char array in setByteArrayRegion as follows:

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

Edit: Also, assuming that the al[i] should be a1[i] you are doing something very dangerous as you are not allocating space for a1. Basically doing as I suggest above means you can get rid of that entire loop. Also don't forget to delete the C++ Array when you have finished with it (ie copied it into the 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;
}
Goz
  • 61,365
  • 24
  • 124
  • 204
  • +1; I would also suggest to use the `len` variable when creating and setting the byte array instead of fix value `100`. – maba Oct 12 '12 at 07:56
  • You could use a std::string or std::vector as temporary container. – MadScientist Oct 12 '12 at 08:12
  • Thank you, Goz and others. error: invalid conversion from `char*' to `const jbyte*' com_sp_dll_NativeMethods.cpp:: error: initializing argument 4 of `void – Renga Oct 12 '12 at 08:57
  • I got the above mentioned error. Sorry to be pest. I am not familiar ith C++ and JNI data types – Renga Oct 12 '12 at 08:59
  • @Renga: Then edit your original question and post up the errors. – Goz Oct 12 '12 at 09:20
  • @Renga: What you are getting is a linker error. Are you sure you've included all the libraries you need? – Goz Oct 12 '12 at 09:31
  • @Goz: Please let me know how to incude libraries.. I dont use any specific libraries. Is there anything that I need to add? I desperately need your help. – Renga Oct 12 '12 at 09:35
  • @Renga: I don't know anything about your build process. But you are using libraries you are using JNI and STL, for example. Show me how you are building and I may be able to help. – Goz Oct 12 '12 at 09:36
  • @Goz: Can I have your email ID? I can mail you the files. – Renga Oct 12 '12 at 09:40
  • @Renga: All I'm after is your GCC & LD command lines ... or, perhaps, your makefile. – Goz Oct 12 '12 at 09:44
  • 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 Is this what you mentioned? – Renga Oct 12 '12 at 10:09
  • @Renga You shouldn't ask for peoples email. The idea with SO is that everything is public. If anyone finds the answer here useful then it wouldn't be good if some part of it is in somebody's mail box. Use the chat functionality instead. It saves all conversations. – maba Oct 12 '12 at 10:22
  • @Renga: TBH I'm not really sure whats wrong with that. You may want to create a new question asking specifically how to compile and link JNI code. You'll probably get a better response than asking in the comments here... – Goz Oct 12 '12 at 10:22
  • @Goz: Thanks a lot for all your help. Qmaba: I am sorry. I am new to this forum. I will not do it again. Thanks again. – Renga Oct 12 '12 at 10:31