您好,我正在研究这个项目:https://github.com/svazqz/plClojure
但目前我在构建 c++ 二进制文件后遇到一个问题,当我在构建步骤后运行文件创建时,我得到:
#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x0000000105d3894c, pid=12933, tid=259
#
# JRE version: OpenJDK Runtime Environment Homebrew (21.0.2) (build 21.0.2)
# Java VM: OpenJDK 64-Bit Server VM Homebrew (21.0.2, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-aarch64)
# Problematic frame:
# V [libjvm.dylib+0x42894c] jni_CallStaticObjectMethodV+0x9c
#
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /Users/$USER/Projects/plClojure/hs_err_pid12933.log
#
# If you would like to submit a bug report, please visit:
# https://github.com/Homebrew/homebrew-core/issues
#
zsh: abort ./bazel-bin/src/pl_clojure
概括而言,与以下内容相关:
Internal exceptions (2 events):
Event: 0.124 Thread 0x000000014880a800 Exception <a 'java/lang/NoClassDefFoundError'{0x0000000787f120c0}: clojure/java/api/Clojure> (0x0000000787f120c0)
thrown [src/hotspot/share/classfile/systemDictionary.cpp, line 301]
Event: 0.124 Thread 0x000000014880a800 Exception <a 'java/lang/NoSuchMethodError'{0x0000000787f123c8}: var> (0x0000000787f123c8)
thrown [src/hotspot/share/prims/jni.cpp, line 1072]
我尝试了不同的方法在项目中添加 clojure jar 文件作为依赖项,但是下载 deps 时
bazel sync
失败,或者在成功下载依赖项并构建二进制文件后二进制文件仍然抛出先前的异常。
如何使用 bazel 添加所需的 jar 文件,然后在 C++ 代码中使用它们?
我尝试过使用这个规则:
http_archive(
name = "rules_clojure",
sha256 = "c841fbf94af331f0f8f02de788ca9981d7c73a10cec798d3be0dd4f79d1d627d",
strip_prefix = "rules_clojure-c044cb8608a2c3180cbfee89e66bbeb604afb146",
urls = ["https://github.com/simuons/rules_clojure/archive/c044cb8608a2c3180cbfee89e66bbeb604afb146.tar.gz"],
)
load("@rules_clojure//:repositories.bzl", "rules_clojure_dependencies", "rules_clojure_toolchains")
rules_clojure_dependencies()
rules_clojure_toolchains()
我希望能够在 C++ 代码中使用 clojure,如下所示:
options[0].optionString = "-Djava.class.path=/Library/external/spec_alpha/spec.alpha-0.1.143.jar:/Library/external/clojure/clojure-1.9.0.jar";
为了能够运行 clojure 代码,抛出 C++ 接口。
2 件事:
void add_path(JNIEnv* env, const std::string& path)
{
const std::string urlPath = "file:/"+path;
jclass classLoaderCls = env->FindClass("java/lang/ClassLoader");
jmethodID getSystemClassLoaderMethod = env- >GetStaticMethodID(classLoaderCls, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
jobject classLoaderInstance = env- >CallStaticObjectMethod(classLoaderCls, getSystemClassLoaderMethod);
jclass urlClassLoaderCls = env->FindClass("java/net/URLClassLoader");
jmethodID addUrlMethod = env->GetMethodID(urlClassLoaderCls, "addURL", "(Ljava/net/URL;)V");
jclass urlCls = env->FindClass("java/net/URL");
jmethodID urlConstructor = env->GetMethodID(urlCls, "<init>", " (Ljava/lang/String;)V");
jobject urlInstance = env->NewObject(urlCls, urlConstructor, env- >NewStringUTF(urlPath.c_str()));
env->CallVoidMethod(classLoaderInstance, addUrlMethod, urlInstance);
std::cout << "Added " << urlPath << " to the classpath." << std::endl;
}
您的 main.cpp 文件将如下所示:
#include <jni.h> /* where everything is defined */
#include <cstring>
void add_path(JNIEnv* env, const std::string& path)
{
const std::string urlPath = "file:/"+path;
jclass classLoaderCls = env->FindClass("java/lang/ClassLoader");
jmethodID getSystemClassLoaderMethod = env->GetStaticMethodID(classLoaderCls, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
jobject classLoaderInstance = env- >CallStaticObjectMethod(classLoaderCls, getSystemClassLoaderMethod);
jclass urlClassLoaderCls = env->FindClass("java/net/URLClassLoader");
jmethodID addUrlMethod = env->GetMethodID(urlClassLoaderCls, "addURL", "(Ljava/net/URL;)V");
jclass urlCls = env->FindClass("java/net/URL");
jmethodID urlConstructor = env->GetMethodID(urlCls, "<init>", " (Ljava/lang/String;)V");
jobject urlInstance = env->NewObject(urlCls, urlConstructor, env- >NewStringUTF(urlPath.c_str()));
env->CallVoidMethod(classLoaderInstance, addUrlMethod, urlInstance);
std::cout << "Added " << urlPath << " to the classpath." << std::endl;
}
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=/Library/external/spec_alpha/spec.alpha-0.1.143.jar:/Library/external/clojure/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;
add_path(env, "path to jar")
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();
}