Reputation: 100
I am trying to create a native method in Java using C++. However, my g++ compiler keeps telling me that my GetByteArrayElements function is not declared. I have included both jni.h and the corresponding header file to my class, I do not know what is wrong. Please help me.
I have tried changing the arguments to see if that was the problem. It was not, putting env
in the front does not help.
#include<algorithm>
#include<string>
#include<vector>
#include<jni.h>
#include"com_package_name_ClassName.h"
#define apnd push_back
#define nperm std::next_permutation
typedef std::vector<std::string> slist;
JNIEXPORT jbyteArray JNICALL Java_com_package_name_ClassName_permute(JNIEnv*env,jclass cls,jbyteArray ba)
{
bool cp=false;
jbyte*bt=GetByteArrayElements(*ba,&cp);
std::string str=std::string((char*)bt,env->GetArrayLength(ba));
std::string*ps=new std::string(),tmp=str;
slist*perms=new slist();
perms->apnd(str);
nperm(tmp.begin(),tmp.end());
while(tmp!=str)
{
perms->apnd(tmp);
nperm(tmp.begin(),tmp.end());
}
for(unsigned int i=0;i<perms->size();*ps+=*perms[i]+(i+1==perms->size()?"":"\n"),i++);
jbyteArray r=env->NewByteArray(ps->size());
env->SetByteArrayRegion(r,0,ps->size(),reinterpret_cast<const char*>(ps->c_str()));
return r;
}
Header File
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_package_name_ClassName */
#ifndef _Included_com_package_name_ClassName
#define _Included_com_package_name_ClassName
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_package_name_ClassName
* Method: permute
* Signature: ([B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_package_name_ClassName_permute
(JNIEnv *, jclass, jbyteArray);
#ifdef __cplusplus
}
#endif
#endif
Upvotes: 0
Views: 788
Reputation: 1033
It should be
For c: jbyte*bt = (*env)->GetByteArrayElements(env,ba,&cp);
For c++: jbyte*bt = env->GetByteArrayElements(ba,&cp);
Upvotes: 1
Reputation: 597016
GetByteArrayElements()
is not a standalone function, like your code is trying to use it as. It is actually a member of the JNIEnv
object that is given to you, just like the GetArrayLength()
, NewByteArray()
, and SetByteArrayRegion()
members are. Please read the JNI documentation.
You are also leaking all of the memory that you allocate. There is no need to use new
at all, let the compiler manage all of the memory for you. And you need to release the Java byte array when you are done accessing its elements.
Try something more like this instead:
#include <algorithm>
#include <string>
#include <vector>
#include <jni.h>
#include "com_package_name_ClassName.h"
#define apnd push_back
#define nperm std::next_permutation
typedef std::vector<std::string> slist;
JNIEXPORT jbyteArray JNICALL Java_com_package_name_ClassName_permute(JNIEnv *env, jclass cls, jbyteArray ba)
{
jbyte *bt = env->GetByteArrayElements(ba, NULL);
if (!bt) return NULL;
std::string str(reinterpret_cast<char*>(bt), env->GetArrayLength(ba));
env->ReleaseByteArrayElements(ba, bt, 0);
std::string tmp = str;
slist perms;
do {
perms.apnd(tmp);
nperm(tmp.begin(), tmp.end());
}
while (tmp != str);
std::string ps = perms[0];
for(size_t i = 1; i < perms.size(); ++i) {
ps += ("\n" + perms[i]);
}
jbyteArray r = env->NewByteArray(ps.size());
if (r) {
env->SetByteArrayRegion(r, 0, ps.size(), reinterpret_cast<const jbyte*>(ps.c_str()));
}
return r;
}
Upvotes: 2