2011-12-27 3 views
3

Я пишу плагин для программы, написанной на C++.Можно ли вызвать код clojure из C++?

Плагины размещаются в определенном каталоге и вызывается основным приложением. Я хотел бы написать большую часть плагина в Clojure (gui, вычисления и т. Д.), Однако фактический «плагин» должен быть написан на C++. Различные данные необходимо передать из C++ в Clojure.

Как это сделать?

JNI/JNA, розетки, системные вызовы? (ничего не знаю много)

+0

Никогда не Clojure, как я не любитель шепелявость или макросов. Краткий обзор wikipedia выглядит так, как будто он работает на виртуальной машине Java, но также поддерживает CLR и может скомпилировать JavaScript. В любом случае это не является родным, поэтому для его вызова из C++ вам понадобится какая-то оболочка DLL, webservice или и то, и другое. – AJG85

+5

В этом вопросе есть две части: 1) как вы вызываете Java из C++ и 2) как вы называете Clojure с Java. Последнее не так сложно, http://clojure.org/java_interop является отправной точкой. Первый вопрос зависит от ваших требований и вашей среды. Для проекта, над которым я работал долгое время, мы использовали сокеты: http://sourceforge.net/projects/jradius/ – Gert

ответ

1

JNI должен быть довольно прост для этого.

я бы подойти к нему так:

  1. развивать свой код Clojure с хорошо определенным внешним интерфейсом, т.е. независимо от набора методов/функций, которые нужно вызвать.
  2. пакет его как автономный uberjar (содержащий Clojure LIBS как а)
  3. написать свой C++ обертку, который необходимо выполнить следующие действия:
    • создать JVM с uberjar на пути к классам (см это ссылка: http://java.sun.com/docs/books/jni/html/invoke.html)
    • загрузить ваш класс Clojure
    • обеспечивают фасад, который отображает C++ функции нижележащих методов Java (Clojure функции)

Вы можете протестировать свою uber-jar с шага 2 с помощью простой автономной тестовой жгуты Java, которая создает основной класс clojure и вызывает соответствующие методы; это даст вам знать, что у вас есть хорошая java/clojure jar, если вы столкнулись с какими-либо проблемами в jni-вызове на шаге 3.

Как вы проверяете ссылки jni, обратите особое внимание на незначительные/тонкие разницы между связи c и C++ jni.

Удачи.

2

Я знаю, что этот вопрос старый, но, возможно, кто-то найдет это полезным.

#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 
Смежные вопросы