Skip to content

Instantly share code, notes, and snippets.

@santa4nt
Last active December 19, 2023 22:50
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 10 You must be signed in to fork a gist
  • Save santa4nt/4a8fd626335e36c94356 to your computer and use it in GitHub Desktop.
Save santa4nt/4a8fd626335e36c94356 to your computer and use it in GitHub Desktop.
Sample JNI/C++ HelloWorld
public class HelloJNI {
static {
System.loadLibrary("hello"); // loads libhello.so
}
private native void sayHello(String name);
public static void main(String[] args) {
new HelloJNI().sayHello("Dave");
}
}
#include "HelloJNIImpl.h"
#include <memory>
#include <functional>
#include <iostream>
#include <jni.h>
#include "HelloJNI.h" // auto-generated by `javah HelloJNI`
using std::string;
using std::function;
using std::unique_ptr;
using std::shared_ptr;
using std::cout;
using std::endl;
class jstring_deleter
{
JNIEnv *m_env;
jstring m_jstr;
public:
jstring_deleter(JNIEnv *env, jstring jstr)
: m_env(env)
, m_jstr(jstr)
{
}
void operator()(const char *cstr)
{
cout << "[DEBUG] Releasing " << cstr << endl;
m_env->ReleaseStringUTFChars(m_jstr, cstr);
}
};
const string ToString(JNIEnv *env, jstring jstr)
{
jstring_deleter deleter(env, jstr); // using a function object
unique_ptr<const char, jstring_deleter> pcstr(
env->GetStringUTFChars(jstr, JNI_FALSE),
deleter );
return string( pcstr.get() );
}
shared_ptr<const char> ToStringPtr(JNIEnv *env, jstring jstr)
{
function<void(const char*)> deleter = // using a lambda
[env, jstr](const char *cstr) -> void
{
cout << "[DEBUG] Releasing " << cstr << endl;
env->ReleaseStringUTFChars(jstr, cstr);
};
return shared_ptr<const char>(
env->GetStringUTFChars(jstr, JNI_FALSE),
deleter );
}
/*
* Class: HelloJNI
* Method: sayHello
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_HelloJNI_sayHello
(JNIEnv *env, jobject thisObj, jstring arg)
{
DoSayHello(ToString(env, arg));
//const string name = ToStringPtr(env, arg).get();
//DoSayHello(name);
}
void DoSayHello(const string &name)
{
cout << "Hello, " << name << endl;
}
#ifndef _HELLO_JNI_IMPL_H
#define _HELLO_JNI_IMPL_H
#include <string>
void DoSayHello(const std::string &name);
#endif//_HELLO_JNI_IMPL_H
export JAVA_INC=/usr/lib/jvm/java-7-oracle/include
# step 1: compile the .class file with invocation to a native method
javac HelloJNI.java
# step 2: auto-generate a .h header file from said Java source
javah HelloJNI
# step 3: make the shared library with the name linked in said Java source, and implementing said native method
g++ -std=c++11 -shared -fPIC -I$JAVA_INC -I$JAVA_INC/linux HelloJNIImpl.cpp -o libhello.so
# step 4: run JVM with java.library.path set to include said shared library
java -Djava.library.path=. HelloJNI
@gevorgyana
Copy link

gevorgyana commented Jun 18, 2019

Thanks a lot for this guide! It is also very interesting how use this with Gradle.

@Cvar1984
Copy link

Nice

@cmjagtap
Copy link

Thanks

@pktiuk
Copy link

pktiuk commented Feb 9, 2021

This gist helped me a lot.
Thanks

@tomekatomek123456789
Copy link

Thanks, this hist helped me.

@wermos
Copy link

wermos commented Jan 20, 2022

This is outdated at this point. javah was removed in JDK 10. The modern equivalent of line 6 (JDK >= 10) in makerun.sh is javac -h . HelloJNI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment