Erlang NIF的使用

Erlang NIF的使用,第1张

Erlang NIF的使用

        Native Implemented Functions(NIF)可以用C来实现程序一些功能的扩展,一般用来实现一些用Erlang无法实现或者实现效率低的功能。

      C语言编译生成的动态库(*.so)在Erlang调用C模块时动态加载到Erlang的进程空间中,调用NIF不用上下文的切换开销,但是安全性不是很高,因为NIF的crash会导致整个Erlang进程crash。

NIF的实现

先按官方文档上给的例子,初次实现一下NIF的使用:

1.创建niftest.c文件
#include "erl_nif.h"

static ERL_NIF_TERM hello(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
{
    return enif_make_string(env, "Hello world!", ERL_NIF_LATIN1);
}

static ErlNifFunc nif_funcs[] =
{
    {"hello", 0, hello}
};

ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)

初始化NIF库:
通过初始化宏将C实现和对应的Erlang模块绑定起来;
ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL)
第一个参数 : 对应erlang模块的名称
第二个参数 : 是该库中所有可供外部调用的NIF的函数描述符的静态数组

函数描述符用数据结构ErlNifFunc来表示:

typedef struct
{
    const char* name;
    unsigned arity;
    ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
}ErlNifFunc;

name表示在Erlang中调用的函数名;  arity表示函数的参数个数;
fptr是一个指向函数的指针,它是这个函数对应的C语言实现

 在C语言中实现的NIF函数的定义方式:

static ERL_NIF_TERM  FuncName(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])   

第一个参数总是ErlNifEnv,代表着函数调用的上下文环境, 可以通过它得到对应的NIF模块的某些特定数据;
参数列表argv是由Erlang传过来的参数,参数个数是argc;
如果在函数中需要使用传过来的参数,就要用enif_get_*函数将argv解析成对应的数据类型,如int, float等;
输出(函数返回)的数据,要将C的数据类型转换成ERL_NIF_TERM,C返回给Erlang的数据的转换过程是通过enif_make_*函数实现;

2. 相应的erlang模块niftest.erl实现:
-module(niftest).

-export([init/0, hello/0]).

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

hello() ->
    "NIF library not loaded".

 通过load_nif函数加载niftest.so

3.编译niftest.c文件

niftest.c将被编译为共享库niftest.so,以供在需要调用的时候加载

在linux平台下:

gcc -fPIC -shared -o niftest.so niftest.c -I $ERL_ROOT/usr/include/

gcc编译生成共享库niftest.so:
-fPIC : 告诉编译器产生与位置无关代码 (Position-Independent Code)。这样一来,产生的代码中就没有绝对地址了,全部使用相对地址,所以代码可以被加载到内存的任意位置,都可以正确的执行;
-shared : 表明产生共享库;
-o : 指定生成可执行文件的名称
-I :  指定头文件目录
$ERL_ROOT : 为erlang-otp的安装路径

4. 调用nif函数

调用结果:

 可以看到在加载nif后就可以调用niftest.c中的函数了
 

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5097603.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-16
下一篇 2022-11-17

发表评论

登录后才能评论

评论列表(0条)

保存