Can I call clojure code from C++?

前端 未结 2 627
有刺的猬
有刺的猬 2021-01-05 12:05

I\'m writing a plugin for a program written in C++.

Plugins are placed in a specific dir and get called by the main application. I would like to write most of the pl

相关标签:
2条回答
  • 2021-01-05 12:49

    JNI should be pretty straightforward for this.

    I would approach it this way:

    1. develop your clojure code with a well defined external interface, ie, whatever set of methods/functions you need to invoke.
    2. package it as a standalone uber-jar (containing the clojure libs as well)
    3. write your c++ wrapper, which must do the following:
      • create the jvm with your uberjar on the classpath (see this link: http://java.sun.com/docs/books/jni/html/invoke.html )
      • load your clojure class
      • provide a facade that maps c++ functions to the underlying java methods (clojure functions)

    You can test your uber-jar from step 2 via a simple standalone java test harness that creates the main clojure class and invokes the appropriate methods; this will let you know that you have a good java/clojure jar in case you run into any issues in the jni invocation in step 3.

    As you check the jni references pay particular attention to the slight/subtle calling differences between the c and c++ jni linkages.

    Good luck.

    0 讨论(0)
  • 2021-01-05 12:54

    I know this question is old but maybe somebody find this useful.

    #include <jni.h>       /* where everything is defined */
    #include <cstring>
    
    int main() {
        JavaVM *jvm;       /* denotes a Java VM */
        JNIEnv *env;       /* pointer to native method interface */
        JavaVMInitArgs vm_args; /* JDK/JRE 6 VM initialization arguments */
        JavaVMOption* options = new JavaVMOption[1];
        options[0].optionString = "-Djava.class.path=/home/raoof/.m2/repository/org/clojure/spec.alpha/0.1.143/spec.alpha-0.1.143.jar:/home/raoof/.m2/repository/org/clojure/clojure/1.9.0/clojure-1.9.0.jar";
        vm_args.version = JNI_VERSION_1_6;
        vm_args.nOptions = 1;
        vm_args.options = options;
        vm_args.ignoreUnrecognized = false;
        /* load and initialize a Java VM, return a JNI interface
         * pointer in env */
        JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
        delete options;
    
        jclass Clojure = env->FindClass("clojure/java/api/Clojure");
        jmethodID var = env->GetStaticMethodID(Clojure, "var", "(Ljava/lang/Object;Ljava/lang/Object;)Lclojure/lang/IFn;");
        jobject load_string = env->CallStaticObjectMethod(Clojure, var, env->NewStringUTF("clojure.core"), env->NewStringUTF("load-string"));
        jmethodID load_string_invoke = env->GetMethodID(env->GetObjectClass(load_string), "invoke", "(Ljava/lang/Object;)Ljava/lang/Object;");
        env->CallObjectMethod(load_string, load_string_invoke, env->NewStringUTF("(prn (+ 1 2 3 4 5))"));
    
        jvm->DestroyJavaVM();
    }
    

    and then

    g++ -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux/ -L/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server -ljvm clojurejvm.cpp
    LD_LIBRARY_PATH=/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server ./a.out
    
    0 讨论(0)
提交回复
热议问题