I have a swig wrapper for jni # ndk.
The function header is:
//
// Created by Tomasz on 03/11/2017.
//
#ifndef PC_ANDORID_APP_RESIZE_GIF_H
#define PC_ANDORID_APP_RESIZE_GIF_H
int Version();
int ResizeAnimation(const char * infile, const char * outfile);
#endif //PC_ANDORID_APP_RESIZE_GIF_H
The swig interface is simple as this:
%module GifResizer
%inline %{
#include "resize-gif.h"
extern int Version();
extern int ResizeAnimation(const char * infile, const char * outfile);
%}
and the implementation of ResizeAnimation is:
int ResizeAnimation(const char * infile, const char * outfile) {
initialize();
/* ... */
return 0;
}
The problem is, that value of params in Swig generater wrapper:
SWIGEXPORT jint JNICALL Java_org_imagemagick_GifResizerJNI_ResizeAnimation(JNIEnv *jenv, jclass jcls, jstring jarg1, jstring jarg2) {
jint jresult = 0 ;
char *arg1 = (char *) 0 ;
char *arg2 = (char *) 0 ;
int result;
(void)jenv;
(void)jcls;
arg1 = 0;
if (jarg1) {
arg1 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg1, 0);
if (!arg1) return 0;
}
arg2 = 0;
if (jarg2) {
arg2 = (char *)(*jenv)->GetStringUTFChars(jenv, jarg2, 0);
if (!arg2) return 0;
}
result = (int)ResizeAnimation((char const *)arg1,(char const *)arg2);
jresult = (jint)result;
if (arg1) (*jenv)->ReleaseStringUTFChars(jenv, jarg1, (const char *)arg1);
if (arg2) (*jenv)->ReleaseStringUTFChars(jenv, jarg2, (const char *)arg2);
return jresult;
}
is okay and the arg1 and arg2 have proper values, but once ResizeAnimation is called, the pointers point to different memory address, and infile (arg1) is null, while outfile (arg2) is some random memory.
All the sources are built with standard android CMake for NDK.
The problem was caused by running x86_64 code on x86 emulator. Silly :)
Related
Want to generate random string of fix length from JNI function for that i have used below function
static const char alphanum[] =
"abcdefghijklmnopqrstuvwxyz";
jstring Utils::getRandomString(JNIEnv *env, const int len) {
char s[len];
for (int i = 0; i < len; ++i) {
int p = rand() % (sizeof(alphanum) - 1);
s[i] = alphanum[p];
}
s[len] = 0;
__android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "getRandomString %s", s);
jstring temp= env->NewStringUTF(s);
return temp;
}
but application get crash for line jstring temp= env->NewStringUTF(s); only for ABI version armeabi-v7a
for the solution i have tried this solution
jstring Utils::getRandomString(JNIEnv *env, const int len) {
char s[len];
for (int i = 0; i < len; ++i) {
int p = rand() % (sizeof(alphanum) - 1);
s[i] = alphanum[p];
}
s[len] = 0;
__android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "getRandomString 2 %s", s);
jbyteArray array = env->NewByteArray(len);
env->SetByteArrayRegion(array, 0, len, (const jbyte *) s);
jstring strEncode = env->NewStringUTF("UTF-8");
jclass cls = env->FindClass("java/lang/String");
jmethodID ctor = env->GetMethodID(cls, "<init>", "([BLjava/lang/String;)V");
jstring object = (jstring) env->NewObject(cls, ctor, array, strEncode);
__android_log_print(ANDROID_LOG_DEBUG, "LOG_TAG", "getRandomString 3 %s",
env->GetStringUTFChars(object, 0));
// jstring temp= env->NewStringUTF(s);
return object;
}
but it working fine for ABI version armeabi-v7a when we execute same code on ABI x86 it returning unexpected output like PKdhtXMmr18n2L9K�ؾ�����-DL
please provide some solution that return generated string. env->NewStringUTF() working for ABI version x86 it get crash on armeabi-v7a.
thanks in advance
Android Studio 2.3.2
Gradle experimental 0.9.2
Last NDK.
I wrote a small function in C that is invoked through JNI in Java but returns a string that precedes characters that should not be there.
This is the C function:
char * text() {
char * txt = "a";
char * ret = malloc(strlen(a)+2);
strcat(ret,txt);
strcat(ret,"b");
return ret;
}
This is the JNI C to return to Java
JNIEXPORT jstring JNICALL
Java_com_myapp_Main_getMsg(JNIEnv *env, jobject instance, jstring var)
{
char * msg = text();
return (*env)->NewStringUTF(env, msg );
}
This is Java call:
static {
System.loadLibrary("myapp");
}
public native String getMsg(String var);
String stringreturnedfromC = getMsg("eee");//eee is not used
This show this:
_Main_getMsgab
but should return only "ab".
This is a strange behavior. Why? And how can I get just the right string?
Noticed your function text() is not correct.
Do something like this
char * text() {
char * txt = "a";
char * ret = (char *)malloc(strlen(txt)); //malloc(strlen(a)+2); is incorrect statment
strcat(ret,txt);
strcat(ret,"b");
return ret;
}
I have a problem for parsing float from char in JNI-Android Application.This is my sample data :
0.00618567 0.00224441 0.002006603 0.001813437 0.003761207 -0.001850192 -0.001011893 -0.00342476 0.003790586 0.002385935 0.002647488 0.004411637 0.005938921 0.00698391 0.004522655 0.001524881 -0.002673242 -0.0002569943 -0.002495839 0.00230171 0.000844161 0.006387557 0.008135659 0.005583601 0.002238941 -0.001932641 -0.003518643 -0.0006784072 0.001636732 0.001213515 0.0021472 0.004911256 0.003613603 0.001362842 -0.0002172031 -0.002115535 -0.0002000824 0.001085831 0.003149634 0.003899722 0.004865647 0.002436467 0.0001896242 -0.001678405 -0.001909177 -0.002954236 0.001802054 0.003751467 0.004150682 0.005844797 0.002612064 0.003680898 -0.0005450704 -0.002621638 -0.002253087 0.0005009398 0.004602027 0.003445318 0.00632045 0.002706638 -0.001308871 -0.002082631 -0.001821213 -0.0005696003 0.002069579 0.006264412 0.004593662 0.005836432 0.0009420562 -0.003753015 -0.004050847 -0.001744672 -0.002664186 0.00101941 0.004568859 0.003175343 0.005315124
And this is a type of data vector<float> for hog.setSVMdetector(const vector<float>& detector):
0.05359386f, -0.14721455f, -0.05532170f, 0.05077307f, 0.11547081f, -0.04268804f, 0.04635834f, -0.05468199f, 0.08232084f, 0.10424068f, -0.02294518f, 0.01108519f, 0.01378693f, 0.11193510f, 0.01268418f, 0.08528346f, -0.06309239f, 0.13054633f, 0.08100729f, -0.05209739f, -0.04315529f, 0.09341384f, 0.11035026f, -0.07596218f
this is my sample code .cpp in JNI :
extern "C"
jboolean
Java_com_example_franksyesipangkar_tourguide_CameraPreview_ImageProcessing
(JNIEnv* env, jobject thiz, jint width, jint height, jbyteArray NV21FrameData, jintArray outPixels, jbyteArray b)
{
LOGD("JNIEnv");
//convert jbyteArray to char
jbyte *cmd = env->GetByteArrayElements(b, 0);
LOGD("JNIEnvFeature");
//char * feature = (char *)cmd;
char feature[90600];
memset(feature,0, sizeof(feature));
memcpy(feature, cmd, strlen((char*)cmd));
In this code, a data in char feature which I want to parsing it to data like a type of data hog.setSVMdetector(const vector<float>& detector).So, do you have an idea ?
Maybe this can help you:
#include <iostream>
#include <vector>
#include <strstream>
#include <string>
std::vector<float> parse_delimeted_list_of_numbers(char* line, char delimeter)
{
std::vector<float> vector_of_numbers;
std::istrstream input_stream(line);
std::string text;
float number;
while (std::getline(input_stream, text, delimeter)) {
sscanf_s(text.c_str(), "%f", &number, text.size());
vector_of_numbers.push_back(number);
}
return vector_of_numbers;
}
// A program to test that the above function works well
int _tmain(int argc, _TCHAR* argv[])
{
// auto vector_of_numbers = parse_delimeted_list_of_numbers("234.0, 345, 465, 46456.0",',');
auto vector_of_numbers = parse_delimeted_list_of_numbers("234.0 34 465 46456.0", ' ');
for (auto number : vector_of_numbers)
std::cout << number << "\n";
return 0;
}
char* (*loadDex) (char * dexPath, char * odexPath,int flag) = NULL;
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
char* (*loadDex) (char *, char *,int) = NULL;
LOGD("JNI_OnLoad!");
void *ldvm = (void*) dlopen("/system/lib/libdvm.so", RTLD_LAZY);
if(ldvm == NULL)
{
LOGD("ERROR : %s",dlerror());
//is art
void *ldvm = (void*) dlopen("/system/lib/libart.so", RTLD_LAZY);
}
loadDex = (char* (*) (char *, char *,int)) dlsym (ldvm, "loadDex");
void *venv;
if ((*vm)->GetEnv(vm, (void**) &venv, JNI_VERSION_1_4) != JNI_OK)
{
return -1;
}
return JNI_VERSION_1_4;
}
I use dlsym() function in order to get the pointer of loadDex() but it returns 0. Anyone here can teach me how to get the exact pointer?
Thanks in advance!
loadDex was a private API of dalvik and doesn't exist in ART. This sort of thing should just be done in Java.
I am developing a Decoder using android NDK and FFmpeg native libraries. I have put Native Support for the project using Android Tools and I have the C code in videodecoder.cpp file. In the file the following function gives me this problem
JNIEXPORT jint Java_ssrp_android_ffmpegdecoder_H264Decoder_consumeNalUnitsFromDirectBuffer(
JNIEnv* env, jobject thiz, jobject nal_units, jint num_bytes,
jlong pkt_pts) {
DecoderContext *ctx = get_ctx(env, thiz);
void *buf = NULL;
if (nal_units == NULL) {
D("Received null buffer, sending empty packet to decoder");
} else {
buf = env->GetDirectBufferAddress(nal_units);
if (buf == NULL) {
D("Error getting direct buffer address");
return -1;
}
}
AVPacket packet = {.data = (uint8_t*) buf, .size = num_bytes, .pts = pkt_pts };
int frameFinished = 0;
int res = avcodec_decode_video2(ctx->codec_ctx, ctx->src_frame,&frameFinished, &packet);
if (frameFinished)
ctx->frame_ready = 1;
return res;
}
At the line AVPacket packet = {.data = (uint8_t*) buf, .size = num_bytes, .pts = pkt_pts };
It says that `Statement has no effect "AVPAcket" and
At the line int res = avcodec_decode_video2(ctx->codec_ctx, ctx->src_frame,&frameFinished, &packet);
It says that Invalid arguments '
Candidates are:
int avcodec_decode_video2(AVCodecContext *, AVFrame *, int *, const AVPacket *)'
The Problem is
AVPacket packet = {.data = (uint8_t*) buf, .size = num_bytes, .pts = pkt_pts }
as the Compiler does not understand the type / initialization.
This leads to the invalid argument error.
Maybe split the line into:
AVPacket packet;
packet.data = (uint8_t*) buf;
packet.size = num_bytes;
packet.pts = pkt_pts;
This should get more clear error output.