compiling a Clojure library to a shared native library (.so, .dylib) with Graalvm native-image

栏目: IT技术 · 发布时间: 4年前

内容简介:To use sci as a shared libary from e.g. C++, follow along with this tutorial. We illustrate what is happening when you run the scriptInThis file is compiled into a Java class with one static method,

Libsci

To use sci as a shared libary from e.g. C++, follow along with this tutorial. We illustrate what is happening when you run the script libsci/compile .

In libsci/src we have the following Clojure file:

(ns sci.impl.libsci
  (:require [cheshire.core :as cheshire]
            [sci.core :as sci])
  (:gen-class
   :methods [^{:static true} [evalString [String] String]]))

(defn -evalString [s]
  (sci/binding [sci/out *out*] ;; this enables println etc.
    (str (sci/eval-string
          s
          ;; this brings cheshire.core into sci
          {:namespaces {'cheshire.core {'generate-string cheshire/generate-string}}}))))

This file is compiled into a Java class with one static method, evalString . This will be our API for the native library. To make this library more interesting, we enable println by providing a value for *out* in the interpreter. Also we make the cheshire library available, just to show that you can bring in your own Clojure functions.

Now let's have a look at the bridging class between Java and C++:

package sci.impl;

import org.graalvm.nativeimage.c.function.CEntryPoint;
import org.graalvm.nativeimage.c.type.CCharPointer;
import org.graalvm.nativeimage.c.type.CTypeConversion;
import com.oracle.svm.core.c.CConst;

public final class LibSci {
    @CEntryPoint(name = "eval_string")
    public static @CConst CCharPointer evalString(@CEntryPoint.IsolateThreadContext long isolateId, @CConst CCharPointer s) {
        String expr = CTypeConversion.toJavaString(s);
        String result = sci.impl.libsci.evalString(expr);
        CTypeConversion.CCharPointerHolder holder = CTypeConversion.toCString(result);
        CCharPointer value = holder.get();
        return value;
    }
}

Here we wrap the static method evalString into a native library function that is given the name eval_string . We use GraalVM's API to convert between Java and C types.

The Clojure and Java code is compiled into .class files. Next, we compile those .class files into a shared library using native-image :

$ $GRAALVM_HOME/bin/native-image \
  -jar $SCI_JAR \
  -cp libsci/src \
  -H:Name=libsci \
  --shared \
  ...

This begets the files graal_isolate_dynamic.h , graal_isolate.h , libsci.h , libsci.dylib (on linux libsci.so ) and libsci_dynamic.h . We move all these files to libsci/target .

Let's use the library from a C++ program now. Here's the code:

#include <iostream>
#include <libsci.h>

int main(int argc, char* argv[]) {
  graal_isolate_t *isolate = NULL;
  graal_isolatethread_t *thread = NULL;

  if (graal_create_isolate(NULL, &isolate, &thread) != 0) {
    fprintf(stderr, "initialization error\n");
    return 1;
  }

  char *result = eval_string((long)thread, &argv[1][0]);
  std::cout << result << std::endl;
  return 0;
}

This code gets the first command line argument and feeds it into libsci 's function eval_string . We compile this code as follows:

$ g++ libsci/src/from_cpp.cpp -L libsci/target -I libsci/target -lsci -o libsci/target/from_cpp

To run, we first have to set an environment variable to locate the shared libary:

$ export DYLD_LIBRARY_PATH=libsci/target

On linux this environment variable is called LD_LIBRARY_PATH .

Now, let's run it.

$ time libsci/target/from_cpp "
(println :foo)
(require '[cheshire.core :as cheshire])
(cheshire/generate-string {:a 1})"

:foo
{"a":1}
libsci/target/from_cpp   0.01s user 0.01s system 64% cpu 0.026 total

It worked. First we printed a keyword from within the interpreter. Then we returned a Clojure hash-map that was converted into JSON by cheshire. And then we printed the JSON string from the C++ program.

References


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

疯狂Java讲义

疯狂Java讲义

李刚 / 电子工业出版社 / 2008-10 / 99.00元

《疯狂Java讲义》2000年至今,Java语言一直是应用最广的开发语言,并拥有最广泛的开发人群。如今,Java已经不再简单地是一门语言,它更像一个完整的体系,一个系统的开发平台。更甚至,它被延伸成一种开源精神。 《疯狂Java讲义》深入介绍了Java编程的相关方面,全书内容覆盖了Java的基本语法结构、Java的面向对象特征、Java集合框架体系、Java泛型、异常处理、Java GUI编......一起来看看 《疯狂Java讲义》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具