google / jni-bind

JNI Bind is a set of advanced syntactic sugar for writing efficient correct JNI Code in C++17 (and up).

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

HelloWorld Sample

coralblocks opened this issue · comments

#127

@jwhpryor

If you would like to file a new issues for "Distribution to third party projects" that would be great
please change the bug name and file it against me

It is known that starting a JVM from native is a work under development at the moment. But starting a JVM and calling some C++ code from this JVM should be very well supported and documented.

I suggest a step-by-step guide, on the front page, to do the following on Linux and/or MacOS:

1. Compile the Java code:

public class HelloWorld {

    public void sayHello(int count, String msg) {
        for(int i = 0; i < count; i++) {
            System.out.println("Hello JNI-Bind! => " + msg);
        }
    }

    private native void callCppThatWillCallSayHello();

    public static void main(String[] args) {
        (new HelloWorld()).callCppThatWillCallSayHello();
    }
}

2. Compile the C++ code:

NOTE: The code below is most probably wrong. I kindly ask the jni-bind author to fix it.

#include "jni_bind_release.h"
#include "HelloWorld.h"

// 1: Setup JNI Bind in your OnLoad call (needed only once).
std::unique_ptr < jni::JvmRef < jni::kDefaultJvm >> jvm;

extern "C" {
    JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * pjvm, void * ) {
        jvm.reset(new jni::JvmRef < jni::kDefaultJvm > (pjvm));
        return JNI_VERSION_1_6;
    }
}

JNIEXPORT void JNICALL Java_HelloWorld_callCppThatWillCallSayHello
  (JNIEnv * env, jobject obj) {

    static constexpr jni::Class kClass {
        "HelloWorld",
        jni::Method {
            "sayHello",
            jni::Return < void > {},
            jni::Params < jint > {},
            jni::Params < jstring > {}
        }
    };

    const char * cmsg = "Awesome";
    jstring msg = env->NewStringUTF(cmsg.c_str());

    jni::LocalObject < kClass > obj {}; // Constructs new instance.
    obj("sayHello", (jint) 3, msg);

     env->DeleteLocalRef(msg);
}

3. Run the Java code

4. See the Hello World output in your terminal

5. Celebrate 🍾

In case someone is interested, with help from the author (thanks, Jamieson!) I was able to get this working for MacOS and Linux. You can check it here: https://github.com/coralblocks/JavaToCppAndBack#java-calling-c-which-calls-java

Thanks for your help! For sample code, you can indeed take a look at the link above. There are also some samples in javatests.

As for the sample code above, there's no support pure native only usage, but I'm going to rename the title to be a bit more descriptive for what you're asking for.

I just realised #127 goes into some detail on this so I'm going to rename that issue and mark this duplicate.

I might be missing something when you say:

As for the sample code above, there's no support pure native only usage, but I'm going to rename the title to be a bit more descriptive for what you're asking for.

I'm initiating control from Java, in other words, I'm calling C from Java and not Java from C. So not sure what you mean by pure native.

See my entry-point below:

package com.coralblocks.javatocppandback.jni_bind;

public class HelloWorld {

    static {
        System.loadLibrary("HelloWorld");
    }

    public void sayHello(int count, String msg) {
        for(int i = 0; i < count; i++) {
            System.out.println("Hello CoralBlocks from JNI-Bind! => " + msg);
        }
    }

    private static native void goToNativeSide(int count, String msg);

    private static native void tearDownJvm();

    public static void main(String[] args) throws Exception {
        int count = Integer.parseInt(args[0]);
        String msg = args[1];
        goToNativeSide(count, msg);
        tearDownJvm(); // for JNI-Bind, this is necessary to avoid an exception when the JVM exits...
    }
}

Yikes, sorry, I mentally crossed wires with this issue and the other pretty hard. I think I must have recalled that you had two separate issues (no Helloworld, initiate from native) and fused them in my head, sorry about that, I'm trying to clean out some of the issues.

That said, I still think your issue should be considered done (roughly), as there are helloworld samples in https://github.com/google/jni-bind/tree/main/javatests/com/jnibind/test as well as your own Coralblocks site (which, thanks again for doing!).

I'll change the bug name back. Although, if I think the issue ought to be closed (If you disagree feel free to chime back).