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

Can I call clojure code from C++?

本文关键字:代码 clojure 调用 c++ 我可以      更新时间:2023-10-16

我正在为一个用c++编写的程序编写一个插件。

插件被放置在一个特定的目录中,由主应用程序调用。我想在Clojure (gui,计算等)中编写大部分插件,但实际的"插件"需要用c++编写。各种数据需要从c++传递到Clojure。

我该怎么做?

JNI/JNA, socket,系统调用?

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

#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

JNI应该非常简单。

我将这样处理它:

    使用定义良好的外部接口开发clojure代码;也就是说,你需要调用的任何一组方法/函数。
  1. 将它打包成一个独立的超级jar包(包含clojure库))
  2. 编写c++包装器,它必须完成以下操作:
    • 用你的uberjar在类路径上创建jvm(参见这个链接:http://java.sun.com/docs/books/jni/html/invoke.html)加载clojure类
    • 提供一个facade,将c++函数映射到底层java方法(clojure函数)

你可以通过一个简单的独立java测试工具来测试第2步中的ber-jar,它创建了主clojure类并调用了适当的方法;这将让您知道您有一个好的java/clojure jar,以防您在第3步的jni调用中遇到任何问题。

当您检查jni引用时,请特别注意c和c++ jni链接之间细微的调用差异。

好运。