我可以从C ++调用clojure代码吗?

时间:2011-12-27 23:52:44

标签: c++ clojure interop

我正在为用C ++编写的程序编写插件。

插件放在特定目录中,并由主应用程序调用。我想在Clojure(gui,计算等)中编写大部分插件,但实际的“插件”需要用C ++编写。需要将各种数据从C ++传递给Clojure。

我该怎么做?

JNI / JNA,套接字,系统调用? (我对此一无所知)

2 个答案:

答案 0 :(得分:4)

我知道这个问题很老但也许有人觉得这个问题很有用。

#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();
}

然后

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

答案 1 :(得分:1)

JNI应该非常直截了当。

我会这样接近:

  1. 使用定义良好的外部接口开发您的clojure代码, 即,您需要调用的任何方法/函数集。
  2. 将它打包为独立的超级jar(包含clojure库) 孔)
  3. 编写你的c ++包装器,它必须执行以下操作:
  4. 你可以通过一个简单的独立java测试工具测试你的超级jar,从而创建主要的clojure类并调用适当的方法;如果您在第3步中遇到jni调用中的任何问题,这将告诉您有一个好的java / clojure jar。

    在检查jni引用时要特别注意c和c ++ jni链接之间的轻微/微妙的调用差异。

    祝你好运。