?

Log in

No account? Create an account
entries friends calendar profile Previous Previous Next Next
SiDen
В данном посте я хочу привести небольшой пример эрланговской nif на окамле.
Итак, что для начала почитать:
http://www.erlang.org/doc/man/erl_nif.html
http://caml.inria.fr/pub/docs/manual-ocaml/manual032.html

Напишем небольшую функцию sample, результатом которой будет ее единственный аргумент.

На стороне эрланга nif_sample.erl:
-module(nif_sample).

-export([
        init/0,
        sample/1,
        selftest/0
]).

init() ->
        erlang:load_nif("./nif_sample", 0).

sample(_) ->
        throw({error, "NIF library 'nif_sample' not loaded"}).

selftest() ->
        init(),
        sample(sample).


Прослойка на C.
nif_sample.c:
#include <stdio.h>
#include <erl_nif.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>


static ERL_NIF_TERM sample(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
        return ocaml_sample_wrapper(argc, argv);
}

static ErlNifFunc nif_funcs[] =
{
        {"sample", 1, sample}
};

static int load(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info)
{
        caml_startup(0);
        return 0;
}

ERL_NIF_INIT(nif_sample, nif_funcs, &load, NULL, NULL, NULL)


ocaml_sample.c:
#include <stdio.h>
#include <string.h>
#include <erl_nif.h>
#include <caml/mlvalues.h>
#include <caml/callback.h>

void* ocaml_sample_wrapper(int argc, const ERL_NIF_TERM argv[])
{
        static value * ocaml_sample = NULL;
        if (ocaml_sample == NULL)
                ocaml_sample = caml_named_value("sample_wrapper");
        return caml_callback(*ocaml_sample, argv[0]);
}


Ну и непосредственно сам окамл sample_wrapper.ml:
let sample_wrapper a =
        a

let _ = Callback.register "sample_wrapper" sample_wrapper


Как все это хозяйство собрать:

ocamlc -custom -output-obj -o sample_wrapper.o sample_wrapper.ml
ocamlc -c -I /usr/local/lib/erlang/usr/include/ ocaml_sample.c
cp /usr/local/lib/ocaml/libcamlrun.a libocamlsample.a
ar r libocamlsample.a sample_wrapper.o ocaml_sample.o
gcc -fPIC -shared -flat_namespace -undefined suppress -o nif_sample.so nif_sample.c -I/usr/local/lib/erlang/usr/include/ -I/usr/local/lib/ocaml/ libocamlsample.a
erlc nif_sample.erl


Что же в конечном итоге вышло:
Erlang R14B02 (erts-5.8.3) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.3  (abort with ^G)
1> nif_sample:selftest().
sample

Tags:

7 comments or Leave a comment