`
xumingyong
  • 浏览: 182408 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Another erlang nif test

阅读更多

from http://www.davispj.com/2009/11/23/erlang-nif-test.html

NOTE

This tutorial requires a fairly recent snapshot of Erlang. I'm using the snapshot from November 22nd, 2009. The official release containing the required functionality is slated to be out on November 25th, 2009. You'll see I haven't actually installed the snapshot build in case you're like me and want to wait for an official release.

UPDATE

No more NIF's! The daily snapshot page was updated and the new tarball for today doesn't include the new NIF functions. Luckily there are public mirrors of the code.

$ git clone git://github.com/janl/erlang0d.git otp_src_R13B03
$ cd otp_src_R13B03
$ git checkout origin/R13B03-20091122225501

Erlang NIF's

I've been waiting excitedly for the new Natively Implemented Function (NIF) interface to land in the next Erlang release since I first saw them announced. Then I saw another message form @dizzyco that was more specific. So I did what any normal person would do. Read the test suite and wrote a minimal NIF to figure out the compiling and call semantics.

The NIF Module C API

The first thing to note is that a NIF module has four callbacks that are used for bookkeeping with loading the shared library code: load, reload, upgrade, and unload. Each function gets an ErlNifEnv* argument, a pointer to some driver specific data, and (except unload) an ERL_NIF_TERM load_info argument. The environment and private data pointers are pretty standard for this sort of thing. I'm not entirely certain what load_info is for. The method for initializing NIF modules takes a second parameter which may be what this is for, but I haven't investigated to find out for certain.

After defining each of those four methods, to actually implement the NIF functions we define a function that takes an ErlNifEnv* argument and zero or more positional parameters of type ERL_NIF_TERM. These functions will show up in the Erlang side and can be called as expected.

 

The code for our minimal NIF module looks like this:

// mynif.c
#include <stdio.h>
#include "erl_nif.h"

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

static int
reload(ErlNifEnv* env, void** priv, ERL_NIF_TERM load_info)
{
    return 0;
}

static int
upgrade(ErlNifEnv* env, void** priv, void** old_priv,
          ERL_NIF_TERM load_info)
{
    return 0;
}

static void
unload(ErlNifEnv* env, void* priv)
{
    return;
}

static ERL_NIF_TERM
do_something(ErlNifEnv* env, ERL_NIF_TERM a1)
{
    unsigned long val;
    if(!enif_get_ulong(env, a1, &val)) {
        return enif_make_badarg(env);
    } else {
        return enif_make_ulong(env, val*2);
    }
}

static ErlNifFunc mynif_funcs[] =
{
    {"do_something", 1, do_something}
};

ERL_NIF_INIT(mynif, mynif_funcs, load, reload, upgrade, unload)

That's all fairly straight forward. Define the four required functions and just return 0 to indicate no error. The ErlNifFunc structure appears to be a triple of {name_in_erlang, arity, name_in_c} calls. There's an example in the source on having the same Erlang name and different arities. As you'd expect, you just specify the same string, and change the second value.

The implementation of do_something shows a basic error when the argument is not an unsigned long. We'll test that this works as expected later.

The Erlang API

The Erlang side is pretty simple as well. To load a NIF module we just call erlang:load_nif/2. The first parameter is the path to the shared object to load. The second parameter I just specify as 0 to follow the test code, I've not investigated its use though I assume it shows up in the load_info argument in the module API.

Another thing to note is that the NIF module and its corresponding Erlang module have overlapping function namespaces. When we define a function in the NIF module, it shows up in our Erlang module. The tests use a pattern to throw an error if the Erlang function gets called. In other words, when we load the NIF module it replaces the Erlang definition, so if we hit the Erlang definition we report an error.

Our Erlang code looks like this:

// mynif.erl
-module(mynif).
-export([start/0, do_something/1]).

start() ->
    erlang:load_nif("mynif", 0).

do_something(_Val) ->
    nif_error(?LINE).    

nif_error(Line) ->
    exit({nif_not_loaded,module,?MODULE,line,Line}).

Building the Modules

Building appears to just be the standard shared object style. I happened to have an example lying around from my earlier work on an EEP0018 module (which I'll definitely be revisiting now). The linker dark magic is outside this simple example, but there are plenty of places that will explain this. I haven't tested the Linux flags, but they should work just fine.

// Makefile
OTPROOT=/Users/davisp/tmp/otp_src_R13B03/
INCLUDES = -I$(OTPROOT)/erts/emulator/beam/

# OS X flags.
#GCCFLAGS = -O3 -fPIC -bundle -flat_namespace -undefined suppress -fno-common -Wall

# Linux Flags
GCCFLAGS = -O3 -fPIC -shared -fno-common -Wall

CFLAGS = $(GCCFLAGS) $(INCLUDES)
LDFLAGS = $(GCCFLAGS) $(LIBS)

OBJECTS = mynif.o

DRIVER = mynif.so
BEAM = mynif.beam

all: $(DRIVER) $(BEAM)

clean: 
    rm -f *.o *.beam $(DRIVER)

$(DRIVER): $(OBJECTS)
    gcc -o $@ $^ $(LDFLAGS)

$(BEAM): mynif.erl
    erlc $^
# EOF

With all three of those files in your $CWD you should be able to just run make and have the proper output in the same directory.

Running the Example

A sample console log to show that it behaves as expected:

$ ~/tmp/otp_src_R13B03/bin/erl
Erlang R13B03 (erts-5.7.4) [source] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false]

Eshell V5.7.4  (abort with ^G)
1> mynif:start().
ok
2> mynif:do_something(0).
0
3> mynif:do_something(2).
4
4> mynif:do_something(nil).
** exception error: bad argument
     in function  mynif:do_something/1
        called as mynif:do_something(nil)
5> mynif:do_something(2.3). 
** exception error: bad argument
     in function  mynif:do_something/1
        called as mynif:do_something(2.3)

 

 

And there you have it. This is fairly exciting stuff. I've already got a list of projects I'm going to play with integrating into the NIF API to see what type of speedups I can get.

 

 

 

分享到:
评论

相关推荐

    erlang nif test

    在"erlang nif test"这个项目中,我们很显然看到这是一个关于测试Erlang NIF功能的演示。 Erlang是一种面向并发、分布式计算的函数式编程语言,它的设计目标是构建高可用、容错性强的系统。NIFs是Erlang与C交互的...

    rustler编写erlang nif

    【标题】:“rustler编写erlang nif” 在Erlang生态系统中,Native Implemented Functions (NIFs) 是一种机制,允许开发者用其他语言(如C、C++或Rust)编写性能关键部分的代码,然后在Erlang虚拟机(VM)中调用。...

    erl_nif_rustler_过程宏写法

    在Erlang中,`NIF (Native Implemented Functions)` 是一种机制,允许开发者使用其他语言(如C或Rust)编写高效性能的代码,并在Erlang虚拟机中调用。本篇主要介绍如何利用Rust语言来开发Erlang NIF,并探讨`erl_nif...

    rustler —用于创建Erlang NIF函数的安全Rust桥-Rust开发

    示例Rustler是一个用于以安全的Rust代码编写Erlang NIF的库。 这意味着应该没有任何办法。 入门指南 示例Rustler是一个用于以安全的Rust代码编写Erlang NIF的库。 这意味着应该没有办法使BEAM(Erlang VM)崩溃。 该...

    erlpuzzle:Erlang NIF 到 libpuzzle,一个快速查找视觉相似图像的库

    ErlPuzzle - Erlang 的 libpuzzle NIF Puzzle 库旨在快速找到视觉上相似的图像(gif、png、jpg),即使它们已被调整大小、重新压缩、重新着色或稍微修改。 该库是免费的、轻量级的但非常快速、可配置、易于使用,...

    Windows下使用NIF扩展Erlang完整例子

    Windows下使用NIF扩展Erlang完整例子,包含nif工程项目,erlang引用例子。 配套文章:http://blog.csdn.net/mycwq/article/details/17527485

    erlang-rust-nif:在 Rust 中实现的 Erlang NIF 示例

    Rust 中的 Erlang NIF 这是一个如何在 Rust 中实现 NIF 的示例。 它对我有用,也可能对你有用,但如果它吃掉了你的作业,请不要生气。 虽然这将是可行的写现实世界的代码下面这个例子,因为整个erl_nif.h接口可用...

    esqlite:sqlite的Erlang NIF

    sqlite3的Erlang nif库。 介绍 该库允许您使用来自erlang的出色的sqlite引擎。 该库以nif库的形式实现,可以最快地访问sqlite数据库。 这可能是有风险的,因为nif库或sqlite数据库中的错误可能会使整个Erlang VM...

    用于创建 Erlang NIF 函数的安全 Rust 桥

    盗贼文档|入门|例子Rustler 是一个用安全的 Rust 代码编写 Erlang NIF 的库。这意味着应该没有办法让 BEAM (Erlang VM) 崩溃。该库提供了用于生成与 BEAM 交互的样板的工具,处理 Erlang 术语的编码和解码,并在它们...

    erl_nif 扩展erlang的另外一种方法

    在Erlang中,为了实现与C或其他低级语言的高效交互,Erlang提供了一个名为`erl_nif`的接口。本文将深入探讨`erl_nif`,了解它是如何扩展Erlang的功能,并讨论如何使用它来提升性能。 `erl_nif`(Erlang NIF,Native...

    rustler:用于创建Erlang NIF函数的Safe Rust桥

    Rustler是一个关键工具,它允许开发人员使用Rust语言安全地构建Erlang的Native Interface (NIF)函数。NIF是Erlang虚拟机(VM)提供的一种机制,使得Erlang代码能够调用C或C++编写的库,从而利用这些语言的高性能特性...

    wpi:用于 Raspberry Pi 的 WiringPi 库的 Erlang NIF

    wpi - 用于 Raspberry Pi 的 WiringPi 库的 Erlang NIF 此应用程序是围绕库的 Erlang 包装器,该库是 Arduino 的 Wiring 库的 Raspberry Pi 方言。 wpi 使得读取和写入 GPIO 引脚、写入 LCD、移入和移出位或通过...

    erlang-tc:Erlang NIF用于threshold_crypto

    2. **测试**:使用`make test`命令,这通常会运行一个测试套件,确保NIFs在Erlang环境中正确工作且没有错误。测试对于验证NIF的正确性和安全性至关重要,因为不当使用NIFs可能会导致Erlang进程崩溃,影响整个系统的...

    erlang port driver test

    Port Driver 可能与其他 Erlang 外部接口技术,如 NIF(Native Implemented Function)或 ETS(Erlang Term Storage)进行了对比。 标签 "erlang post driver test" 强调了测试的焦点是关于 Erlang 的 Port Driver...

    erlsha2:在Erlang NIF中实现的SHA-224,SHA-256,SHA-384,SHA-512

    在Erlang NIF中实现的SHA-224,SHA-256,SHA-384,SHA-512。描述erlsha2库应用程序使用Erlang NIF实施SHA-2安全哈希标准(SHA-224,SHA-256,SHA-384,SHA-512)。 (它也提供纯的Erlang实现,尽管它们比C NIF实现慢...

    enif_protobuf:使用enif(Erlang nif)的Google Protobuf实现

    **enif_protobuf** 是一个基于 **Erlang NIF (Native Implemented Functions)** 的库,用于集成 **Google Protobuf**,使得在Erlang环境中能够方便地处理和序列化protobuf消息。Erlang NIF是一种机制,允许Erlang...

    re2:RE2正则表达式库的Erlang NIF绑定

    RE2正则表达式库的Erlang NIF绑定 使用re2 考虑到RE2的差异,该库的API尽可能遵循标准的Erlang / OTP re API。 $ erl 1&gt; re2:run("Bar-foo-Baz", "FoO", [caseless]). {match,[&lt;&lt;"foo"&gt;&gt;]} 2&gt; re2:replace(...

    bitwise:用于显示Erlang调度程序问题的Erlang NIF示例

    按位:NIF示例显示Erlang调度程序的问题bitwise模块实现了几个Erlang本机实现函数(NIF),旨在显示NIF对Erlang调度程序线程可能产生的几种不同影响。 该模块提供的功能的几个变体exor/2采用一个二进制和一个字节值...

    erlang版本的protobuf(erl_protobuffs)

    **protobuf与Erlang** `protobuf`,全称Protocol Buffers,是Google开发的一种数据序列化协议,类似于XML和JSON,但更小巧、快速且高效。它允许开发者定义数据结构,然后生成相应的代码来轻松地读写这些数据,支持...

    druuid:用于 UUID 生成的 Erlang NIF

    德鲁伊概述围绕库的 Erlang NIF 包装器。 目前仅支持 V4 UUID,但即将支持其他版本。建造druuid 存储库包含 OSSP uuid 库的 1.6.2 版。 要构建只需克隆 repo 并键入以下内容:make用法生成一个 v4 uuiddruuid:v4().

Global site tag (gtag.js) - Google Analytics