Wrapping a c++ library using jni - android

I've successfully added a c++ library to the android 2.3.6 source tree.
Now i want to wrap my library in order to be used from java
I've searched a lot in the net about the steps to do so but almost all the examples i've found are hello world examples and simple ones...
From these examples i've understood that i must create a java file calling the native functions that i need with the prefix native ,then generate the headers and implement the c++ file.
But i don't see how can i call my library functions with this manner.
what is the connection between these headers and my function..?
i am really confused now and i dont know how to start
So, i would be thankfull if someone can tell me the step to wrap a c++ library(already integrated in the aosp)

This is quite a complex problem, and probably beyond the scope of a short answer here. The best thing to do, then, would probably be to guide you to some better documents than the ones you have found so far.
This series of blog posts seems particularly helpful: http://thebreakfastpost.com/2012/01/21/wrapping-a-c-library-with-jni-introduction/
You may also find a wrapper autogenerator helpful. There is one that I haven't tried here: http://www.teamdev.com/jniwrapper/features/

If I understood your problem:
Let's say you have a c++ library with this method
int cPlusPlusMethod{
// Your c++ implementation
}
Basically what you have to do is:
Create the java methods that you need
native int javaMethod();
Follow the steps that you saw in the links you found in order to create a c++ header, you will have something like:
JNIEXPORT jint JNICALL Java_yourPackageName_yourJavaClass_javaMethod(JNIEnv *);
Now you have a c++ header with the declarations of all the methods that you need. Write a c++ file that implements that header and copy-paste the c++ implementation of the library.
JNIEXPORT jint JNICALL Java_yourPackageName_yourJavaClass_javaMethod(JNIEnv *env){
// Your c++ implementation
}
(You will have to include all the needed imports and put the other files of the lib in the 'jni' folder.)
Execute ndk-build from your android project root folder, and that's it.
Maybe this is not the smartest way to do it but at least for me it worked.
Obviously this works if you have the library source files, if you are speaking about a static lib, then I'm not able to help you.

Related

Is it enough to wrap exported functions of a C library using JNI for it to work using JNI?

I am interested about the prospects of using any C library using JNI. Particularly with Android, but I assumed this compatibility should be the same as being compatible with JNI.
Without being an original developer of some C library, I've found it confusing to know, what methods I need to register in JNI_OnLoad (https://developer.android.com/training/articles/perf-jni#native-libraries).
To progress, I figured out with the help of https://stackoverflow.com/a/4514781/4959635 to call
nm myclib.a | grep " T "
to find a list of (supposed) "exported functions". However, the nm output may well tell other things as well.
Now my question is,
will/could/should a library work, if I wrap only the exported functions via JNI_OnLoad?
Or do I need to ensure other qualities in the library in order to guarantee that it will work with JNI?
On the other hand, I read some other discussions such as:
https://www.thecodingforums.com/threads/unsatisfiedlinkerror-when-loading-shared-lib.360242/
which suggested that having undefined symbols might mean that the C code is not structured properly for JNI.
Whereas this resource:
https://www.baeldung.com/jni
seems to suggest that wrapping exported functions is in fact what's expected.
No. Functions you call from JNI must always follow a specific signature: (ignoring the return type for now)
fun(JNIEnv *env, jobject obj, ...)
or
fun(JNIEnv *env, jclass cls, ...)
where the remaining arguments are types that the JVM can process.
You will need to create wrapper functions that go between the JVM types and whatever types your functions expect. See the SWIG library for a potential means of auto-generating these wrappers, but know you will still need to write quite a bit of custom code.

Can't remove an empty folder in C++

I want to remove an empty folder using remove() in C++ on Windows 7 but I can't. I tried rmdir() instead of remove() then the folder got removed!
Nevertheless, the reason why I don't use rmdir() is due to Android. In a library project for Android, I can't include "direct.h" header so can't use rmdir(), either. Unlike on Windows, the function remove() works well on Android. I don't understand why.
Anybody knows why this is happening?
Or any other functions which will work on both Windows and Android?
This is a pretty common problem when writing cross-platform programs.
Sometimes, a library can provide the abstraction you need. For example, Boost has a filesystem library that can enumerate files, manipulate directories, etc., on multiple platforms using the exact same code.
Also, there are usually symbols defined that allow you to detect which compiler is currently building your code. Even if there isn't one that does what you want, you can define your own.
Let's say you need to build your software for two different fictitional operating systems named FooOS and for BarOS. I'm going to invent two symbols, FOO_OS and BAR_OS. In my code, I can do something like this:
#ifdef FOO_OS
#include <foo_stuff.h>
#elseif BAR_OS
#include <bar_stuff.h>
#endif
void do_something()
{
#ifdef FOO_OS
do_it_this_way();
#elseif BAR_OS
do_it_that_way();
#endif
}
Now, we just need to either define FOO_OS or BAR_OS. This can be done through an IDE's project configuration or on the command line of the compiler. Use Google to find out about your particular situation, since you didn't include those details in your post.
There is a preprocessing step when you compile your code that makes a pass through the source, and applies these conditional statements. A following pass actually compiles the code. Here is some documentation about Visual Studio's preprocessor, for example.

How setup libsvm in Android?

Im trying to setup libsvm in android to detect motion from accelerometer. I have no idea how to setup libsvm in android and how to use it. guys can you give clue for this ?
You do not setup libsvm, simply use the library wrapper for the language you are using to develop an app for android (Java I guess?). Wrapper is included in the official release. And it also includes the sample of usage of this particular library. There is nothing special here - if you know how to develop android app, then using additional library should not be a problem. If you do not know how to develop such an app - then starting from motion recognition is a bad idea. The same applies for ability to use SVM for anything. If you haven't ever used SVM it would be better to start with something simplier, like writing the "non mobile" version of the app and getting familiar with this model. Otherwise, probability of failing is quite big.
Sorry for my previous wrong answer format
Since the libsvm is written in C, you can easily wrap the code via JNI interface and use libsvm in Java.
A wrapper can be found in: https://github.com/yctung/AndroidLibSvm
For example, once you import this project in Android studio, you can call
jniSvmTrain(String options);
to make the svm training with the same interface of original libsvm.
If you look at the code, it is simply a wrapper of original "svm-train.c" in libsvm
#include "./libsvm/svm-train.h"
// helper function to be called in Java for making svm-train
extern "C" void Java_edu_umich_eecs_androidlibsvm_MainActivity_jniSvmTrain(JNIEnv *env, jobject obj, jstring cmdIn){
const char *cmd = env->GetStringUTFChars(cmdIn, 0);
debug("jniSvmTrain cmd = %s", cmd);
std::vector<char*> v;
// add dummy head to meet argv/command format
std::string cmdString = std::string("dummy ")+std::string(cmd);
cmdToArgv(cmdString, v);
// make svm train by libsvm
svmtrain::main(v.size(),&v[0]);
// free vector memory
for(int i=0;i<v.size();i++){
free(v[i]);
}
// free java object memory
env->ReleaseStringUTFChars(cmdIn, cmd);
}
"Setuping" I think you are asking to add the jar file the LIBSVM provide as a library to your android studio project. You can take a look here:
Android Studio: Add jar as library?
In the LIBSVM website you can download a zip file with the JAVA jar file inside and examples of usage.

JNI, NDK, and OpenCV

I have recently begun using the Android NDK and I have successfully implemented a few simple Android apps. I need to detect objects (squares and rectangles) from an image. My research has shown me that OpenCV is the solution for this. This is the algorithm I use to detect a square from the image.
However, I am unclear as to how should I use the squares.cpp file in my code. The OpenCV samples show how to use the cpp files in JNI format. Do I need to convert the squares.cpp file to JNI or would there be another feasible solution?
Thanks. All suggestions and feedback are welcome.
You don't have to convert the squares.cpp file to JNI.
From your Java code, you will call a JNI function (as I suppose you did in the "few simple Android apps" you have implemented) that will then call the functions in squares.cpp.
In other words, you basically only need one call to a JNI function from Java, and once you are in the C++ code, you can code in C++ as usual.

Passing Camera.MAIN in Unity3D to android java method

i'm working on integrating image recognition app using Moodstocks SDK ,
to start the scanner in moodstocks i must use a surfaceview (Camera) , all works fine when i do it in eclipse , but i want to use unity3D cause i'm making it in a sort of a game ,
so i made my eclipse project as JAR and imported it in unity and i'm trying to call the method in my java class from the unity script and pass the camera.Main to it
so if you can give me any guidelines about that
Thanks,
There are several ways to create a Java plugin but the result in each case is that you end up with a .jar file containing the .class files for your plugin. One approach is to download the JDK, then compile your .java files from the command line with javac. This will create .class files which you can then package into a .jar with the jar command line tool. Another option is to use the Eclipse IDE together with the ADT.
Once you have built your Java plugin (.jar) you should copy it to the Assets->Plugins->Android folder in the Unity project. Unity will package your .class files together with the rest of the Java code and then access the code using the Java Native Interface (JNI). JNI is used both when calling native code from Java and when interacting with Java (or the JavaVM) from native code.
To find your Java code from the native side you need access to the Java VM. Fortunately, that access can be obtained easily by adding a function like this to your C/C++ code:
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* jni_env = 0;
vm->AttachCurrentThread(&jni_env, 0);
}
This is all that is needed to start using Java from C/C++. It is beyond the scope of this document to explain JNI completely. However, using it usually involves finding the class definition, resolving the constructor () method and creating a new object instance, as shown in this example:-
jobject createJavaObject(JNIEnv* jni_env) {
// find class definition
jclass cls_JavaClass = jni_env->FindClass("com/your/java/Class");
// find constructor method
jmethodID mid_JavaClass = jni_env->GetMethodID (cls_JavaClass, "<init>", "()V");
// create object instance
jobject obj_JavaClass = jni_env->NewObject(cls_JavaClass, mid_JavaClass);
// return object with a global reference
return jni_env->NewGlobalRef(obj_JavaClass);
}
This explanation comes from this information page, where a few examples are written as well. You should take a look over here! This may be worth a read as well.
Disclaimer: I work for Moodstocks.
The ScannerSession object in the Moodstocks SDK for Android is designed to be a high-level, easy-to-use wrapper that takes care of many "technical" difficulties by itself, in the context of a classic, Java app. In particular, it initializes the camera for you, previews it on the provided SurfaceView and dispatches camera frames to the Moodstocks SDK.
I've never used Unity myself so I can't dive into the details, but I think that in your context, given the fact that Unity has its own way of initializing and using the camera, you'll have to bypass this ScannerSession object and hit lower-level functions of the Moodstocks SDK. Find how to get the camera frames using Unity, and feed them manually to the Moodstocks SDK Scanner object. You can take inspiration from what is done in the ScannerSession to see how to do that!
Hope this helps! If you're looking for more advice, you can ask us questions on the Moodstocks Help Center

Categories

Resources