erl_nif

erl_nif

C库

erl_nif

库摘要

用于ErlangNIF库的API函数。

描述

NIF库包含本地实现的Erlang模块的一些功能。本地实现的函数(NIF)与其他函数一样被调用,与调用者没有任何区别。如果在成功加载NIF库之前调用该函数,则每个NIF都必须在Erlang中实现该实现。典型的这种存根实现是抛出异常。但是如果NIF库没有为某些架构实现,它也可以用作后备实现。

警告

使用此功能时要格外小心。

本机函数作为VM本机代码的直接扩展执行。执行不是在安全的环境中进行的。VM不可能提供与执行Erlang代码相同的服务,例如抢占式调度或内存保护。如果本机函数的行为不太好,整个VM就会出现错误。

  • 崩溃的本机函数将使整个VM崩溃。

  • 错误实现的本机函数可能导致VM内部状态不一致,这可能导致VM崩溃,或者在调用本机函数之后的任意一点上VM的各种错误行为。

  • 返回之前执行lengthy work的本机函数会降低虚拟机的响应速度,并可能导致混杂的奇怪行为。这种奇怪的行为包括但不限于极端的内存使用,以及调度程序之间的负载平衡不佳。Erlang/OTP版本之间因长时间工作而出现的奇怪行为也会有所不同。

  • ErlNifTime

  • ErlNifTimeUnit

  • enif_monotonic_time()

  • enif_time_offset()

  • enif_convert_time_unit()

I/O队列

Erlang nif库包含一些函数,可以方便地处理unix系统调用所使用的I/O向量。writevI/O队列不是线程安全的,因此必须使用其他的同步机制。

  • SysIOVec

  • ErlNifIOVec

  • enif_ioq_create()

  • enif_ioq_destroy()

  • enif_ioq_enq_binary()

  • enif_ioq_enqv()

  • enif_ioq_deq()

  • enif_ioq_peek()

  • enif_inspect_iovec()

  • enif_free_iovec()

写入文件描述符时的典型用法如下所示:

int writeiovec(ErlNifEnv *env, ERL_NIF_TERM term, ERL_NIF_TERM *tail, ErlNifIOQueue *q, int fd) { ErlNifIOVec vec, *iovec = &vec; SysIOVec *sysiovec; int saved_errno; int iovcnt, n; if (!enif_inspect_iovec(env, 64, term, tail, &iovec)) return -2; if (enif_ioq_size(q) > 0) { /* If the I/O queue contains data we enqueue the iovec and then peek the data to write out of the queue. */ if (!enif_ioq_enqv(q, iovec, 0)) return -3; sysiovec = enif_ioq_peek(q, &iovcnt } else { /* If the I/O queue is empty we skip the trip through it. */ iovcnt = iovec->iovcnt; sysiovec = iovec->iov; } /* Attempt to write the data */ n = writev(fd, sysiovec, iovcnt saved_errno = errno; if (enif_ioq_size(q) == 0) { /* If the I/O queue was initially empty we enqueue any remaining data into the queue for writing later. */ if (n >= 0 && !enif_ioq_enqv(q, iovec, n)) return -3; } else { /* Dequeue any data that was written from the queue. */ if (n > 0 && !enif_ioq_deq(q, n, NULL)) return -4; } /* return n, which is either number of bytes written or -1 if some error happened */ errno = saved_errno; return n; }

长期运行的NIF

正如warning本手册页开头部分所述,本机函数返回速度相当快是非常重要的。很难给出一个原生函数允许工作的确切的最大时间量,但通常一个行为良好的本地函数会在1毫秒内返回给调用者。这可以通过使用不同的方法来实现。如果您完全控制要在本机函数中执行的代码,最好的方法是将工作划分为多个工作块并多次调用本机函数。但是,这并不总是可行的,例如在调用第三方库时。

enif_consume_timeslice()函数可用于通知运行时系统有关NIF呼叫的长度。它通常总是被使用,除非NIF执行得非常快。

如果NIF调用太长,必须通过以下方式之一来处理,以避免响应性降低,调度程序负载平衡问题以及其他奇怪行为:

产生NIF

如果可以拆分长期运行的NIF的功能,从而可以通过一系列较短的NIF调用来完成其工作,则应用程序有两个选项:

  • 从Erlang级别进行一系列NIF调用。

  • 调用一个NIF,该NIF首先执行一个工作块,然后调用enif_schedule_nif函数来调度另一个NIF调用以执行下一个块。然后,以这种方式调度的最后调用可以返回总体结果。

以这种方式分解一个长期运行的函数,使VM能够在对NIF的调用之间重新获得控制权。

这种方法总是比下文所述的其他备选办法更可取。这既从性能角度,也从系统特性角度。

螺纹NIF

这是通过将工作分派到由NIF库管理的另一个线程、从NIF返回并等待结果来完成的。线程可以使用以下方法将结果发送回Erlang进程enif_send下面提供了有关线程原语的信息。

Dirty NIF

只有当仿真程序配置了脏调度程序支持时,才能获得脏NIF支持。从ERTS版本9.0开始,在运行时系统上默认启用了脏调度程序支持,并提供了smp支持。没有SMP支持的Erlang运行时可以执行支持脏调度器,即使在显式启用脏调度程序支持时也是如此。若要在运行时检查是否存在脏调度程序线程,代码可以使用enif_system_info()API函数

不能拆分且不能在毫秒或更短时间内执行的NIF称为“脏NIF”,因为它执行Erlang运行时系统的普通调度程序无法干净处理的工作。使用这些函数的应用程序必须向运行时指示函数是脏的,以便能够进行特殊处理。这是通过在一组称为脏调度器的单独调度器上执行脏作业来处理的。在脏调度程序上执行的脏NIF不具有与普通NIF相同的持续时间限制。

把肮脏的工作分类正确是很重要的。I/O绑定作业应分类为I/O作业,CPU绑定作业应归类为I/O作业。如果将CPU绑定作业归类为I/O绑定作业,脏I/O调度器可能会使普通调度程序挨饿。受I/O约束的作业需要阻止等待I/O,和/或花费有限的时间移动数据。

要安排一个脏的NIF执行,应用程序有两个选项:

  • 在其ErlNifFunc条目中为脏NIF设置适当的标志值。

  • 调用enif_schedule_nif时,向它传递一个指向要执行的NIF的指针,并用参数指示flags它是否期望该操作受CPU限制或I/O限制。

在I/O绑定和CPU绑定之间交替的作业可以重新分类并重新调度,enif_schedule_nif以便它始终在正确类型的脏调度器上执行。有关更多信息,请参阅erl(1)命令行参数的文档+SDcpu+SDio

当一个进程执行一个肮脏的NIF时,一些与它通信的操作可能需要很长时间才能完成。执行脏NIF的进程的暂停或垃圾收集在脏NIF返回之前无法完成。因此,等待这些操作完成的其他进程可能需要等待很长时间。阻止多计划,即呼叫erlang:system_flag(multi_scheduling, block),也可能需要很长时间才能完成。这是因为在块操作完成之前,所有脏调度器上的所有正在进行的脏操作都必须完成。

但是,许多与执行脏NIF的进程通信的操作可以在执行脏NIF时完成。例如,通过erlang:process_info、设置其组长、注册/注销其名称等。

执行脏NIF的进程的终止只能在执行脏NIF时完成到某一点。所有的Erlang资源,例如其注册名称和ETS表格,都已发布。所有链接和监视器都被触发。然而,NIF的执行并未停止。NIF可以安全地继续执行,分配堆内存等,但最好尽快停止执行。NIF可以检查当前进程是否正在使用enif_is_current_process_alive。通信用enif_sendenif_port_command也跌落时的发送过程是不是还活着。某些内部资源(如进程堆和进程控制块)的取消分配被延迟,直到肮脏的NIF完成。

初始化

ERL_NIF_INIT(MODULE, ErlNifFunc funcs[], load, NULL, upgrade, unload)

这是初始化NIF库的神奇宏。它将在全局文件范围内进行评估。

MODULEErlang模块的名称作为没有字符串引号的标识符。它被宏所束缚。

funcs是该库中所有已实现的NIF的函数描述符的静态数组。

loadupgrade并且unload是功能的指针。其中一个load或被upgrade称为初始化图书馆。unload被称为释放图书馆。所有内容在下面分别介绍。

第四个参数NULL被忽略。它早期用于reload自OTP 20以来不再支持的deprecated 回调。

如果编译通过静态包含的NIF --enable-static-nifs,则必须STATIC_ERLANG_NIFERL_NIF_INIT声明之前进行定义。

`int(load)( ErlNifEnv env,void priv_data,ERL_NIF_TERM load_info)`**

load在加载NIF库时调用,并且此模块不存在以前加载的库。

*priv_data可以设置为指向一些私人数据,如果库需要保持NIF调用之间的状态。enif_priv_data返回这个指针。*priv_data被初始化为什么NULL时候load被调用。

load_info是第二个参数erlang:load_nif/2

如果load返回非0load可以是,NULL如果不需要初始化。

`int(升级)( ErlNifEnv env,void priv_data, void old_priv_data,ERL_NIF_TERM load_info)`

upgrade在加载NIF库时调用,并且该模块的旧代码包含已加载的NIF库。

作为load,除了*old_priv_data已经包含最后一次调用loadupgrade为旧模块代码设置的值。*priv_data被初始化为什么NULL时候upgrade被调用。它被允许写入两者*priv_data*old_priv_data.

该库无法加载,如果upgrade返回其他任何东西0或如果upgradeNULL

void (*unload)(ErlNifEnv* env, void* priv_data)

unload当清除NIF库所属的模块代码时调用。同一模块的新代码可能存在,也可能不存在。

数据类型

ERL_NIF_TERM

类型变量ERL_NIF_TERM可以指任何Erlang术语。这是一种不透明的类型,它的值只能用作API函数的参数或者用作NIF的返回值。所有ERL_NIF_TERM属于一个环境(ErlNifEnv)。一个术语不能单独破坏,它的有效性直到其环境被破坏。

ErlNifEnv

ErlNifEnv表示可以承载Erlang术语的环境。只要环境有效,环境中的所有术语都是有效的。ErlNifEnv是不透明类型;指向它的指针只能传递给API函数。有两种环境:

进程约束环境

作为第一个参数传递给所有NIF。传递给NIF的所有函数参数都属于该环境。NIF的返回值也必须是属于相同环境的术语。

一个进程绑定环境包含关于调用Erlang进程的瞬态信息。只有在NIF返回之前,环境才作为参数提供的线程有效。因此,在NIF调用之间存储指向进程绑定环境的指针是没有用的,也是危险的。

过程无关环境

通过调用创建enif_alloc_env。这个环境可以用来在NIF呼叫之间存储条款并且用来发送条款enif_send。包含所有术语的独立于流程的环境在您明确使用enif_free_env或使其失效之前一直有效enif_send

列表/元组/映射中包含的所有术语必须与列表/元组/映射本身属于相同的环境。术语可以在环境之间复制enif_make_copy

ErlNifFunc

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

描述NIF的名称、重要性和实现。

fptr

指向实现NIF的函数的指针。

argv

包含传递给NIF的函数参数。

argc

数组长度,即函数的参数。argv[N-1]因此表示NIF的第N个参数。请注意,该参数argc允许相同的C函数实现具有不同arity(但可能具有相同名称)的几个Erlang函数。

flags

0一个常规的NIF(因此它的值可以被静态初始化的ErlNifFunc实例省略)。

flags可以用来指示nif是dirty NIF这将在脏调度程序线程上执行。

如果肮脏的NIF预计受CPU限制,则其flags字段将设置为ERL_NIF_DIRTY_JOB_CPU_BOUNDERL_NIF_DIRTY_JOB_IO_BOUND

如果其中一个ERL_NIF_DIRTY_JOB_*_BOUND设置标志,运行时系统不支持脏调度程序,运行时系统拒绝加载NIF库。

ErlNifBinary

typedef struct { unsigned size; unsigned char* data; } ErlNifBinary;

ErlNifBinary包含有关检查的二进制项的瞬态信息。data的缓冲区的指针。size具有二进制的原始内容的字节。

请注意,这ErlNifBinary是一种半透明类型,您只能阅读字段sizedata

ErlNifBinaryToTerm

枚举可以指定的选项enif_binary_to_term。对于默认行为,请使用值0

从不可信来源接收数据时,请使用选项ERL_NIF_BIN2TERM_SAFE

ErlNifMonitor

这是标识监视器的不透明数据类型。

nif编写器将提供内存,用于在调用时存储监视器。enif_monitor_process运行时系统不存储数据的地址,因此ErlNifMonitor可以作为任何其他数据使用,它可以被复制,在内存中移动,遗忘等等。为了比较两台监视器,enif_compare_monitors一定要用。

ErlNifPid

进程标识符(pid)。与pid术语(实例ERL_NIF_TERM)相比,ErlNifPids是独立的,不受任何限制environmentErlNifPid是一种不透明的类型。

ErlNifPort

一个端口标识符。与端口ID术语(实例ERL_NIF_TERM)相比,ErlNifPorts是独立的,不受任何限制environmentErlNifPort是一种不透明的类型。

ErlNifResourceType

每一个实例ErlNifResourceType表示可以垃圾回收的内存托管资源对象的类。每个资源类型都有一个惟一的名称和一个析构函数,当释放其类型的对象时调用该函数。

ErlNifResourceTypeInit

typedef struct { ErlNifResourceDtor* dtor; ErlNifResourceStop* stop; ErlNifResourceDown* down; } ErlNifResourceTypeInit;

初始化结构读取enif_open_resource_type_x

ErlNifResourceDtor

typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj

资源析构函数的函数原型。

obj参数是指向资源的指针。对析构函数中的资源的唯一允许使用是最后一次访问其用户数据。析构函数保证是资源解除分配之前的最后一个回调。

ErlNifResourceDown

typedef void ErlNifResourceDown(ErlNifEnv* env, void* obj, const ErlNifPid* pid, const ErlNifMonitor* mon

资源向下函数的函数原型,代表enif_monitor_process...obj是资源,pid是正在退出的受监视进程的标识,并且mon是监视器的身份。

ErlNifResourceStop

typedef void ErlNifResourceStop(ErlNifEnv* env, void* obj, ErlNifEvent event, int is_direct_call

代表一个资源停止函数的函数原型enif_selectobj是资源,event是操作系统事件,is_direct_call如果调用是直接调用的,则为true;如果enif_select调度是调度调用(可能来自另一个线程),则为false。

ErlNifCharEncoding

typedef enum { ERL_NIF_LATIN1 }ErlNifCharEncoding;

字符串和原子中使用的字符编码。唯一支持的编码是ERL_NIF_LATIN1ISO Latin-1(8位ASCII)。

ErlNifSysInfo

用于enif_system_info返回有关运行时系统的信息。包含与。相同的内容ErlDrvSysInfo

ErlNifSInt64

本机带符号64位整数类型.

ErlNifUInt64

本机64位整数类型.

ErlNifTime

表示时间的带符号64位整数类型.

ErlNifTimeUnit

NIF API支持的时间单位的枚举:

ERL_NIF_SEC秒数ERL_NIF_MSEC毫秒ERL_NIF_USEC微秒ERL_NIF_NSEC纳秒ErlNifUniqueInteger

列举可以从中请求的属性enif_unique_integer。对于默认属性,请使用值0

ERL_NIF_UNIQUE_POSITIVE

只返回正整数。

ERL_NIF_UNIQUE_MONOTONIC

只返回strictly monotonically increasing与创建时间相对应的整数。

ErlNifHash

枚举可以使用生成的支持的哈希类型enif_hash

ERL_NIF_INTERNAL_HASH

非便携散列函数,它只保证在一个ErlangVM实例中为同一个术语提供相同的哈希。

它需要32位盐值并在其内生成哈希值0..2^32-1

ERL_NIF_PHASH2

可移植的哈希函数,它为相同的Erlang术语提供相同的散列,而不考虑机器架构和ERTS版本。

它忽略盐值并在其内部生成哈希值0..2^27-1

ERL_NIF_INTERNAL_HASH.它对应的慢erlang:phash2/1

SysIOVec

系统I / O矢量,writev在Unix和WSASendWin32上使用。它用在ErlNifIOVec和之中enif_ioq_peek

ErlNifIOVec

typedef struct { int iovcnt; size_t size; SysIOVec* iov; } ErlNifIOVec;

包含iovcnt SysIOVec指向数据的I / O向量。它被enif_inspect_iovec和使用enif_ioq_enqv

ErlNifIOQueueOpts选项来配置一个ErlNifIOQueueERL_NIF_IOQ_NORMAL

创建正常的I/O队列

出口

void *enif_alloc(size_t size)

分配内存size字节。

回报NULL如果分配失败。

int enif_alloc_binary(size_t size, ErlNifBinary* bin)

分配一个大小为size字节的新二进制数。初始化指向的结构bin以引用分配的二进制文件。该二进制文件必须通过enif_release_binary或由所有权转移到Erlang术语enif_make_binaryErlNifBinaryNIF呼叫之间可以保留一个已分配(和拥有)。

回报true关于成功,或false如果分配失败。

ErlNifEnv *enif_alloc_env()

分配一个新的独立于流程的环境。该环境可用于保存不受任何进程约束的术语。这些条款可以稍后复制到流程环境中,enif_make_copy或作为消息发送到流程enif_send

返回指向新环境的指针。

void *enif_alloc_resource(ErlNifResourceType* type, unsigned size)

分配类型的内存托管资源对象。type和大小size字节。

size_t enif_binary_to_term(ErlNifEnv *env, const unsigned char* data, size_t size, ERL_NIF_TERM *term, ErlNifBinaryToTerm opts)

创建一个解释二进制数据的结果,该二进制数据data必须根据Erlang外部术语格式进行编码。不超过size读取字节data。参数opts对应于第二个参数erlang:binary_to_term/2并且必须是0或者ERL_NIF_BIN2TERM_SAFE

在成功时,将结果项存储在*term并返回读取的字节数。回报0如果解码失败或如果opts是无效的。

另见ErlNifBinaryToTermerlang:binary_to_term/2enif_term_to_binary

void enif_clear_env(ErlNifEnv* env)

释放环境中的所有术语并清除它以供重用。环境必须已经分配enif_alloc_env

int enif_compare(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)

返回一个整数< 0if lhs< rhs,0if lhs= rhs和> 0if lhs> rhs。对应于运营商二郎==,/=,=<,<,>=,和>(但不 =:=或=/=)。

int enif_compare_monitors(const ErlNifMonitor *monitor1, const ErlNifMonitor *monitor2)

比较两ErlNifMonitor无论出于什么原因,也可以用来暗示显示器上的某种人为秩序.

返回0if monitor1和monitor2equal,< 0if monitor1< monitor2,and> 0if monitor1> monitor2。

void enif_cond_broadcast(ErlNifCond *cnd)

和...一样erl_drv_cond_broadcast

ErlNifCond *enif_cond_create(char *name)

和...一样erl_drv_cond_create

void enif_cond_destroy(ErlNifCond *cnd)

和...一样erl_drv_cond_destroy

void enif_cond_signal(ErlNifCond *cnd)

和...一样erl_drv_cond_signal

void enif_cond_wait(ErlNifCond *cnd, ErlNifMutex *mtx)

和...一样erl_drv_cond_wait

int enif_consume_timeslice(ErlNifEnv *env, int percent)

向运行时系统提供一个提示,说明当前NIF调用自上次提示以来消耗了多少CPU时间,如果未指定之前的提示,则自NIF启动以来使用多少CPU时间。时间被指定为进程被允许执行Erlang代码的时间的百分比,直到它可以被挂起以便为其他可运行的进程提供时间。调度时间不是一个精确的实体,但通常可以近似为1毫秒。

请注意,要由运行时系统来确定是否以及如何使用这些信息。某些平台上的实现可以使用其他方法来确定消耗的CPU时间。冗长的NIF应该不考虑这个频繁的呼叫。enif_consume_timeslice以确定是否允许继续执行。

论辩percent必须是介于1和100之间的整数。此函数只能从nif调用线程和参数调用。env必须是调用进程的环境。

回报1如果时间已耗尽,则为0.如果1返回时,NIF将尽快返回,以便进程产生结果。

提供此功能是为了更好地支持协同调度,提高系统响应能力,并且更容易防止由于NIF垄断调度程序线程而导致的VM的错误行为。它可以用来划分length work进入多个重复的NIF调用,无需创建线程。

另见warning此手册页开头的文本。

ErlNifTime enif_convert_time_unit(ErlNifTime val, ErlNifTimeUnit from, ErlNifTimeUnit to)

转换val时间单位值from对应的时间单位值。to.结果使用地板函数四舍五入。

val值来转换时间单位。from时间单位val...to返回值的时间单位。

回报ERL_NIF_TIME_ERROR如果使用无效的时间单位参数调用。

另见ErlNifTimeErlNifTimeUnit

ERL_NIF_TERM enif_cpu_time(ErlNifEnv *)

以与格式相同的方式返回CPU时间erlang:timestamp()。CPU时间是当前逻辑CPU从过去的任意点开始执行的时间。如果操作系统不支持读取此值,则enif_cpu_time调用enif_make_badarg

int enif_demonitor_process(ErlNifEnv* env, void* obj, const ErlNifMonitor* mon)

取消先前创建的监视器。enif_monitor_process.论点obj是指向保存监视器和*mon识别监视器。

回报0如果监视器被成功识别并移除。如果无法识别监视器,则返回一个非零值,这意味着它是

  • 从未为此资源创建过

  • 已取消

  • 已触发

  • 将由并发线程触发。

当使用支持SMP的仿真器时,此函数才是线程安全的.。它只能用于来自NIF调用线程的非SMP仿真器.

int enif_equal_tids(ErlNifTid tid1, ErlNifTid tid2)

和...一样erl_drv_equal_tids

void enif_free(void* ptr)

释放分配的内存enif_alloc

void enif_free_env(ErlNifEnv* env)

释放分配给enif_alloc_env.所有在环境中创建的术语也都被释放了。

void enif_free_iovec(ErlNifIOvec* iov)

释放返回的io矢量enif_inspect_iovec。这只有在NULL传递给环境时才需要enif_inspect_iovec

ErlNifIOVec *iovec = NULL; size_t max_elements = 128; ERL_NIF_TERM tail; if (!enif_inspect_iovec(NULL, max_elements, term, &tail, iovec)) return 0; // Do things with the iovec /* Free the iovector, possibly in another thread or nif function call */ enif_free_iovec(iovec

int enif_get_atom(ErlNifEnv* env, ERL_NIF_TERM term, char* buf, unsigned size, ErlNifCharEncoding encode)

NULL在由bufsize 指向的缓冲区中写入一个终止字符串size,该字符串由term编码的原子的字符串表示组成encode

返回写入的字节数(包括终止NULL字符),或者0如果term不是最大长度为的原子size-1

int enif_get_atom_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len, ErlNifCharEncoding encode)

设置*len为编码NULL原子的长度(不包括终止字符的字节数)。termencode

回报true关于成功,或false如果term不是原子。

int enif_get_double(ErlNifEnv* env, ERL_NIF_TERM term, double* dp)

设置*dp为的浮点值term

回报true关于成功,或false如果term不是浮子。

int enif_get_int(ErlNifEnv* env, ERL_NIF_TERM term, int* ip)

设置*ip为的整数值term

true成功返回,或者false如果term不是整数或超出类型的范围int

int enif_get_int64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifSInt64* ip)

设置*ip为的整数值term

回报true关于成功,或false如果term不是整数,或者不在有符号64位整数的界限之外.

int enif_get_local_pid(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPid* pid)

如果term是节点本地进程的PID,此函数初始化PID变量。*pid从那里回来true.否则返回false不进行任何检查,以确定该进程是否处于活动状态。

int enif_get_local_port(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPort* port_id)

如果term标识节点本地端口,此函数将初始化端口变量。*port_id从那里回来true.否则返回false.没有进行检查以确定端口是否还活着。

int enif_get_list_cell(ErlNifEnv* env, ERL_NIF_TERM list, ERL_NIF_TERM* head, ERL_NIF_TERM* tail)

*head*tail从列表list

回报true关于成功,或false如果它不是列表或列表是空的。

int enif_get_list_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len)

设置*len为列表的长度term

回报true关于成功,或false如果term不是一个合适的名单。

int enif_get_long(ErlNifEnv* env, ERL_NIF_TERM term, long int* ip)

设置*ip为长整型值term

true成功返回,或者false如果term不是整数或超出类型的范围long int

int enif_get_map_size(ErlNifEnv* env, ERL_NIF_TERM term, size_t *size)

*size映射中的键值对数。term...

回报true关于成功,或false如果term不是地图。

int enif_get_map_value(ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value)

设置*value为与key地图关联的值map

true成功返回,或者false如果map不是地图或map不包含地图key

int enif_get_resource(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifResourceType* type, void** objp)

设置*objp为指向引用的资源对象term

true成功时返回,或者false如果term不是类型的资源对象的句柄type

int enif_get_string(ErlNifEnv* env, ERL_NIF_TERM list, char* buf, unsigned size, ErlNifCharEncoding encode)

NULL在由bufsize 指向的缓冲区中写入一个终止字符串,该字符串由字符串中size的字符组成list。这些字符是使用编码写入的encode

返回下列内容之一:

  • 写入的字节数(包括终止NULL字符)

  • -size如果字符串由于缓冲区空间而被截断

  • 0如果list不是可以用< encode或size> 编码的字符串1。

写入的字符串总是NULL终止的,除非缓冲区size是< 1。

int enif_get_tuple(ErlNifEnv* env, ERL_NIF_TERM term, int* arity, const ERL_NIF_TERM** array)

如果term是一个元组,此函数设置*array指向包含元组元素的数组,并设置*arity元素的数量。注意,数组是只读的,并且(*array)[N-1]是元组的第N个元素。*array如果元组的重要性为零,则为未定义。

回报true关于成功,或false如果term不是元组。

int enif_get_uint(ErlNifEnv* env, ERL_NIF_TERM term, unsigned int* ip)

设置*ip为无符号整数值term

true成功返回,或者false如果term不是无符号整数或超出类型的范围unsigned int

int enif_get_uint64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifUInt64* ip)

设置*ip为无符号整数值term

回报true关于成功,或false如果term不是无符号整数,也不是无符号64位整数的边界.

int enif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM term, unsigned long* ip)

设置*ip为无符号长整型值term

true成功返回,或者false如果term不是无符号整数或超出类型的范围unsigned long

int enif_getenv(const char* key, char* value, size_t *value_size)

和...一样erl_drv_getenv

int enif_has_pending_exception(ErlNifEnv* env, ERL_NIF_TERM* reason)

true如果未决异常与环境相关联,则返回env。如果reasonNULL指针,则忽略它。否则,如果与env存在关联的未决异常设置*reason为异常项的值。例如,如果enif_make_badarg被调用来设置待处理的badarg异常,则稍后调用enif_has_pending_exception(env, &reason)设置*reason为原子badarg,然后返回true

另见enif_make_badargenif_raise_exception

ErlNifUInt64 enif_hash(ErlNifHash type, ERL_NIF_TERM term, ErlNifUInt64 salt)

term根据指定的哈希ErlNifHash type

被采纳盐的范围(如果有的话)和返回值取决于散列类型。

int enif_inspect_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, ErlNifBinary* bin)

bin用关于二元项的信息初始化指向的结构bin_term

回报true关于成功,或false如果bin_term不是二进制。

int enif_inspect_iolist_as_binary(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifBinary* bin)

初始化bin具有连续缓冲区,其字节内容与iolist.和inspect_binary的数据bin是暂时的,不需要释放。

回报true关于成功,或false如果iolist不是个少年主义者。

int enif_inspect_iovec(ErlNifEnv* env, size_t max_elements, ERL_NIF_TERM iovec_term, ERL_NIF_TERM* tail, ErlNifIOVec** iovec)

填充iovec中提供的二进制文件列表。iovec_term调用中处理的元素数量仅限于max_elements,和tail设置为列表的其余部分。请注意,输出可能比max_elements在一些平台上。

要从任意的iolist创建二进制文件列表,请使用erlang:iolist_to_iovec/1

调用此函数时,iovec应该包含指向NULL或者一个ErlNifIOVec结构,如果可能的话,应该使用它。G.

/* Don't use a pre-allocated structure */ ErlNifIOVec *iovec = NULL; enif_inspect_iovec(env, max_elements, term, &tail, &iovec /* Use a stack-allocated vector as an optimization for vectors with few elements */ ErlNifIOVec vec, *iovec = &vec; enif_inspect_iovec(env, max_elements, term, &tail, &iovec

iovec被调用的nif函数返回之前,该内容是有效的。如果iovecnif调用返回后应该是有效的,则可以在一个NULL环境中调用该函数。如果没有给定环境iovec,则向量中拥有数据,并且必须使用明确释放的数据enif_free_iovec

回报true关于成功,或false如果iovec_term不是一片爱。

ErlNifIOQueue *enif_ioq_create(ErlNifIOQueueOpts opts)

创建一个可用于存储数据的新I / O队列。opts必须设置为ERL_NIF_IOQ_NORMAL

void enif_ioq_destroy(ErlNifIOQueue *q)

销毁I / O队列并释放所有内容

int enif_ioq_deq(ErlNifIOQueue *q, size_t count, size_t *size)

去队列count来自I/O队列的字节。如果size不是NULL,队列的新大小被放置在那里。

回报true关于成功,或false如果I/O不包含count字节。如果失败,队列将保持不变。

int enif_ioq_enq_binary(ErlNifIOQueue *q, ErlNifBinary *bin, size_t skip)

binq跳过第一个skip字节。

回报true关于成功,或false如果skip的大小大于bin二进制数据的任何所有权都被转移到队列中,并且bin将被认为是只读的,其余的NIF调用,然后作为释放。

int enif_ioq_enqv(ErlNifIOQueue *q, ErlNifIOVec *iovec, size_t skip)

iovecq跳过第一个skip字节。

返回true成功,或者false如果skip比规模更大iovec

SysIOVec *enif_ioq_peek(ErlNifIOQueue *q, int *iovlen)

将I/O队列作为指向SysIOVec中的元素数。iovlen.这是将数据从队列中取出的唯一方法。

这个函数不会从队列中删除任何内容,必须使用该函数完成enif_ioq_deq

返回的数组适用于Unix系统调用writev

size_t enif_ioq_size(ErlNifIOQueue *q)

获取大小q

int enif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term是一个原子。

int enif_is_binary(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term是二进制。

int enif_is_current_process_alive(ErlNifEnv* env)

返回true当前正在执行的进程当前是否存在,否则返回false

此函数只能从NIF调用线程中使用,并且可以使用与当前正在执行的进程相对应的环境。

int enif_is_empty_list(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term是一个空列表。

int enif_is_exception(ErlNifEnv* env, ERL_NIF_TERM term)

返回true如果term是个例外。

int enif_is_fun(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term很有趣。

int enif_is_identical(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs)

true如果两个词相同则返回。对应于Erlang运算符=:==/=

int enif_is_list(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term是一份名单。

int enif_is_map(ErlNifEnv* env, ERL_NIF_TERM term)

true如果term是地图则返回,否则返回false

int enif_is_number(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term是个数字。

int enif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term是PID。

int enif_is_port(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term是港口。

int enif_is_port_alive(ErlNifEnv* env, ErlNifPort *port_id)

回报true如果port_id还活着。

当使用支持SMP的仿真器时,此函数才是线程安全的.。它只能用于来自NIF调用线程的非SMP仿真器.

int enif_is_process_alive(ErlNifEnv* env, ErlNifPid *pid)

回报true如果pid还活着。

当使用支持SMP的仿真器时,此函数才是线程安全的.。它只能用于来自NIF调用线程的非SMP仿真器.

int enif_is_ref(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term是一个参考。

int enif_is_tuple(ErlNifEnv* env, ERL_NIF_TERM term)

回报true如果term是个元组。

int enif_keep_resource(void* obj)

添加对资源对象的引用。objenif_alloc_resource.每一次呼叫enif_keep_resource对象必须通过调用enif_release_resource在破坏对象之前。

ERL_NIF_TERM enif_make_atom(ErlNifEnv* env, const char* name)

使用ISO Latin-1编码从NULL终止的C字符串创建原子术语name。如果长度name超过原子允许的最大长度(255个字符),则enif_make_atom调用enif_make_badarg

ERL_NIF_TERM enif_make_atom_len(ErlNifEnv* env, const char* name, size_t len)

name长度为字符串中创建一个原子项lenNULL字符被视为任何其他字符。如果len超过原子允许的最大长度(255个字符),则enif_make_atom调用enif_make_badarg

ERL_NIF_TERM enif_make_badarg(ErlNifEnv* env)

使...badarg从NIF返回的异常,并将其与环境关联。env.一旦NIF或它调用的任何函数调用enif_make_badarg,运行时确保badarg当NIF返回时引发异常,即使NIF试图返回一个非异常项。

返回值enif_make_badarg可以仅用作NIF的返回值(直接或间接)或传递给enif_is_exceptionNIF,但不能传递给其他NIF API函数。

另见enif_has_pending_exceptionenif_raise_exception

在ERTS 7.0(Erlang / OTP 18)enif_make_badarg之前,必须从NIF 返回返回值。如果enif_make_badarg已调用NIF的返回值,则此要求现在被取消。

ERL_NIF_TERM enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin)

生成一个二进制术语bin二进制数据的任何所有权转移到创建的术语中,bin将被认为是只读的,其余的NIF调用,然后作为释放。

ERL_NIF_TERM enif_make_copy(ErlNifEnv* dst_env, ERL_NIF_TERM src_term)

复制一份术语src_term复制是在环境中创建的。dst_env源项可以位于任何环境中。

ERL_NIF_TERM enif_make_double(ErlNifEnv* env, double d)

从a创建浮点术语double。如果参数double不是有限的,或者是NaN,则enif_make_double调用enif_make_badarg

int enif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding encode)

尝试使用编码创建已存在的来自NULL终止C字符串的原子的术语。nameencode

如果原子已经存在,则该函数将该项存储*atom并返回true,否则falsefalse如果长度name超过原子允许的最大长度(255个字符),也会返回。

int enif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding encoding)

尝试从name长度len和编码的字符串中创建已有原子的术语encodeNULL字符被视为任何其他字符。

如果原子已经存在,则该函数将该项存储*atom并返回true,否则falsefalse如果len超过原子允许的最大长度(255个字符),也会返回。

ERL_NIF_TERM enif_make_int(ErlNifEnv* env, int i)

创建一个整数项。

ERL_NIF_TERM enif_make_int64(ErlNifEnv* env, ErlNifSInt64 i)

从带符号的64位整数创建整数项.

ERL_NIF_TERM enif_make_list(ErlNifEnv* env, unsigned cnt, ...)

创建一个普通的长度列表项cnt。期望类型cnt的参数(之后cnt)的数量ERL_NIF_TERM作为列表的元素。

返回空列表,如果cnt是0。

ERL_NIF_TERM enif_make_list1(ErlNifEnv* env, ERL_NIF_TERM e1)ERL_NIF_TERM enif_make_list2(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2)ERL_NIF_TERM enif_make_list3(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3)ERL_NIF_TERM enif_make_list4(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4)ERL_NIF_TERM enif_make_list5(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)ERL_NIF_TERM enif_make_list6(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)ERL_NIF_TERM enif_make_list7(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)ERL_NIF_TERM enif_make_list8(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)ERL_NIF_TERM enif_make_list9(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)

创建一个具有由函数名称指示的长度的普通列表项。enif_make_list如果参数的数量不匹配,则优先使用这些函数(宏)来覆盖可变参数以获得编译时错误。

ERL_NIF_TERM enif_make_list_cell(ErlNifEnv* env, ERL_NIF_TERM head, ERL_NIF_TERM tail)

创建一个列表单元格[head | tail]

ERL_NIF_TERM enif_make_list_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt)

创建一个包含arr长度数组元素的普通列表cnt

返回空列表,如果cnt是0。

ERL_NIF_TERM enif_make_long(ErlNifEnv* env, long int i)

从a创建一个整数项long int

int enif_make_map_put(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, ERL_NIF_TERM* map_out)

让副本地图map_in和插入keyvalue。如果key已经存在map_in,旧的关联值将被替换为value

如果成功,此函数将设置*map_out到新地图并返回true.返回false如果map_in不是地图。

map_in术语必须属于环境env

int enif_make_map_remove(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM* map_out)

如果map map_in包含key,则此函数会复制map_inin *map_out,并删除key相关的值。如果map map_in不包含key*map_out则设置为map_in

回报true关于成功,或false如果map_in不是地图。

map_in术语必须属于环境env

int enif_make_map_update(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM new_value, ERL_NIF_TERM* map_out)

使得地图的副本map_in和替换旧的关联值keynew_value

如果成功,此函数将设置*map_out为新地图并返回truefalse如果map_in不是地图或不包含地图,则返回key

map_in术语必须属于环境env

unsigned char *enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp)

分配大小的二进制文件size字节并创建一个拥有项。在调用NIF返回之前,二进制数据是可变的。这是一种快速创建新二进制文件的方法,而不必使用ErlNifBinary它的缺点是不能在NIF调用之间保留二进制文件,也不能重新分配二进制文件。

返回指向原始二进制数据和设置的指针。*termp二元术语。

ERL_NIF_TERM enif_make_new_map(ErlNifEnv* env)

形成一个空的地图术语。

ERL_NIF_TERM enif_make_pid(ErlNifEnv* env, const ErlNifPid* pid)

从中获得一个pid字词*pid

ERL_NIF_TERM enif_make_ref(ErlNifEnv* env)

创建一个参考erlang:make_ref/0

ERL_NIF_TERM enif_make_resource(ErlNifEnv* env, void* obj)

为由内存管理的资源对象创建一个不透明句柄enif_alloc_resource。没有完成所有权转移,因为资源对象仍然需要发布enif_release_resource。但是,请注意,调用enif_release_resource可以在获取期限后立即发生enif_make_resource,在这种情况下,资源对象在垃圾收集期间被释放。有关更多详细信息,请参阅example of creating and returning a resource object用户指南中的。

由于ERTS 9.0(OTP-20.0),资源项在比较和序列化term_to_binary或在节点之间传递时具有定义的行为。

  • 两个资源项将比较相等,如果它们传递给它们时会产生相同的资源对象指针enif_get_resource

  • 资源项可以用term_to_binary之后,如果资源对象仍然是活动的,则重新创建binary_to_term叫做。阿陈腐资源期限将从binary_to_term如果资源对象已被解除分配。enif_get_resource将返回无效资源项的false。

在将消息中的资源项传递给远程节点并再次返回时,也适用相同的序列化原则。资源项将在所有节点上失效,但资源对象仍然存在于内存中的节点除外。

在ERTS 9.0(OTP-20.0)之前,所有资源术语确实相互比较相等,并清空二进制文件(<<>>)。如果序列化,它们将被重新创建为纯二进制文件。

ERL_NIF_TERM enif_make_resource_binary(ErlNifEnv* env, void* obj, const void* data, size_t size)

创建由资源对象管理的内存的二进制术语。objenif_alloc_resource返回的二进制项包含size指向字节data在调用资源的析构函数之前,必须保持此原始二进制数据的可读性并保持不变。二进制数据可以存储在资源对象的外部,在这种情况下,析构函数负责释放数据。

多个二进制术语可以由同一个资源对象管理。直到最后一个二进制文件被垃圾收集后,才会调用析构函数。这对于返回更大的二进制缓冲区的不同部分非常有用。

与此同时enif_make_resource,没有完成所有权转让。该资源仍然需要与释放enif_release_resource

int enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM list_in, ERL_NIF_TERM *list_out)

*list_out到列表的反向列表。list_in和回报true,或返回false如果list_in不是名单。

此函数仅用于短列表,因为该列表的副本是在NIF返回后才释放的。

list_in术语必须属于环境env

ERL_NIF_TERM enif_make_string(ErlNifEnv* env, const char* string, ErlNifCharEncoding encoding)

创建一个包含NULL-终止字符串string带编码encoding。

ERL_NIF_TERM enif_make_string_len(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding encoding)

创建一个包含字符串string长度len和编码的字符的列表encodingNULL字符被视为任何其他字符。

ERL_NIF_TERM enif_make_sub_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, size_t pos, size_t size)

生成二进制的子二进制bin_term,从零开始pos有一个长度size字节。bin_term必须是二进制或位字符串。pos+size必须小于或等于bin_term

ERL_NIF_TERM enif_make_tuple(ErlNifEnv* env, unsigned cnt, ...)

创建元组的元组术语cnt。期望类型cnt的参数数量(之后cntERL_NIF_TERM作为元组的元素。

ERL_NIF_TERM enif_make_tuple1(ErlNifEnv* env, ERL_NIF_TERM e1)ERL_NIF_TERM enif_make_tuple2(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2)ERL_NIF_TERM enif_make_tuple3(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3)ERL_NIF_TERM enif_make_tuple4(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4)ERL_NIF_TERM enif_make_tuple5(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5)ERL_NIF_TERM enif_make_tuple6(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6)ERL_NIF_TERM enif_make_tuple7(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7)ERL_NIF_TERM enif_make_tuple8(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8)ERL_NIF_TERM enif_make_tuple9(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9)

创建一个元组项,长度由函数名称指示。enif_make_tuple如果参数的数量不匹配,则优先使用这些函数(宏)来覆盖可变参数以获得编译时错误。

ERL_NIF_TERM enif_make_tuple_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt)

创建一个包含arr长度数组元素的元组cnt

ERL_NIF_TERM enif_make_uint(ErlNifEnv* env, unsigned int i)

unsigned int。创建一个整数项。

ERL_NIF_TERM enif_make_uint64(ErlNifEnv* env, ErlNifUInt64 i)

从无符号64位整数创建整数项.

ERL_NIF_TERM enif_make_ulong(ErlNifEnv* env, unsigned long i)

unsigned long int。创建一个整数项。

ERL_NIF_TERM enif_make_unique_integer(ErlNifEnv *env, ErlNifUniqueInteger properties)

返回具有与指定的相同属性的唯一整数erlang:unique_integer/1

env创建整数的环境。

ERL_NIF_UNIQUE_POSITIVEERL_NIF_UNIQUE_MONOTONIC可以作为第二个参数传递,以更改返回的整数的属性。它们可以通过OR:将这两个值组合在一起。

另见ErlNifUniqueInteger

int enif_map_iterator_create(ErlNifEnv *env, ERL_NIF_TERM map, ErlNifMapIterator *iter, ErlNifMapIteratorEntry entry)

map通过初始化指向的结构来创建映射的迭代器iter。参数entry决定迭代器的开始位置:ERL_NIF_MAP_ITERATOR_FIRSTERL_NIF_MAP_ITERATOR_LAST

回报true如果是成功的话,还是假的map不是地图。

映射迭代器仅在环境的生存期内有用。env认为map属于。必须通过调用enif_map_iterator_destroy*

ERL_NIF_TERM key, value; ErlNifMapIterator iter; enif_map_iterator_create(env, my_map, &iter, ERL_NIF_MAP_ITERATOR_FIRST while (enif_map_iterator_get_pair(env, &iter, &key, &value)) { do_something(key,value enif_map_iterator_next(env, &iter } enif_map_iterator_destroy(env, &iter

映射的键值对没有定义的迭代顺序。唯一的保证是在映射所属的环境的生存期内保留单个map实例的迭代顺序。

void enif_map_iterator_destroy(ErlNifEnv *env, ErlNifMapIterator *iter)

破坏由...创建的地图迭代器enif_map_iterator_create

int enif_map_iterator_get_pair(ErlNifEnv *env, ErlNifMapIterator *iter, ERL_NIF_TERM *key, ERL_NIF_TERM *value)

获取当前映射迭代器位置的键和值项。

如果成功,将*key*value和回报true。返回false如果迭代器位于头(第一个条目之前)或尾部(超出最后一项)。

int enif_map_iterator_is_head(ErlNifEnv *env, ErlNifMapIterator *iter)

回报true中频映射迭代器iter在第一个条目之前定位。

int enif_map_iterator_is_tail(ErlNifEnv *env, ErlNifMapIterator *iter)

回报true中频映射迭代器iter在最后一项之后定位。

int enif_map_iterator_next(ErlNifEnv *env, ErlNifMapIterator *iter)

增量映射迭代器指向下一个键值条目。

返回true如果迭代现在定位在一个有效的键值项,或者false如果迭代器位于尾部(超出最后一项)。

int enif_map_iterator_prev(ErlNifEnv *env, ErlNifMapIterator *iter)

递减映射迭代器指向前一个键值项。

返回true如果迭代现在定位在一个有效的键值项,或者false如果迭代器定位在头部(第一项之前)。

int enif_monitor_process(ErlNifEnv* env, void* obj, const ErlNifPid* target_pid, ErlNifMonitor* mon)

从资源开始监视进程。监视进程时,流程退出将导致对提供的down与资源类型关联的回调。

论辩obj是指向用于保存监视器和*target_pid标识要监视的本地进程。

如果mon不是NULL,成功的调用将监视器的标识存储在ErlNifMonitor结构指向mon此标识符用于引用监视器,以便以后使用enif_demonitor_process或与之相比enif_compare_monitors当监视器触发或资源被解除分配时,将自动删除它。

回报0在成功时,<0(如果没有)down如果进程不再活动,则提供回调,并且>0。

当使用支持SMP的仿真器时,此函数才是线程安全的.。它只能用于来自NIF调用线程的非SMP仿真器.

ErlNifTime enif_monotonic_time(ErlNifTimeUnit time_unit)

返回当前Erlang monotonic time注意,负值并不少见。

time_unit返回值的时间单位。

回报ERL_NIF_TIME_ERROR如果使用无效的时间单元参数调用,或者从不是调度程序线程的线程调用。

另见ErlNifTimeErlNifTimeUnit

ErlNifMutex *enif_mutex_create(char *name)

和...一样erl_drv_mutex_create

void enif_mutex_destroy(ErlNifMutex *mtx)

erl_drv_mutex_destroy一样。

void enif_mutex_lock(ErlNifMutex *mtx)

和...一样erl_drv_mutex_lock

int enif_mutex_trylock(ErlNifMutex *mtx)

和...一样erl_drv_mutex_trylock

void enif_mutex_unlock(ErlNifMutex *mtx)

erl_drv_mutex_unlock一样。

ERL_NIF_TERM enif_now_time(ErlNifEnv *env)

返回erlang:now()时间戳。

这一功能已被废弃。

ErlNifResourceType *enif_open_resource_type(ErlNifEnv* env, const char* module_str, const char* name, ErlNifResourceDtor* dtor, ErlNifResourceFlags flags, ErlNifResourceFlags* tried)

创建或接管由字符串标识的资源类型。name并给出它所指向的析构函数。dtor.论点flags可以具有以下值:

ERL_NIF_RT_CREATE创建不存在的新资源类型。ERL_NIF_RT_TAKEOVER打开现有资源类型并接管其所有实例的所有权。提供的析构函数dtor为调用NIF库尚未创建的现有实例和新实例调用。

两个标志值可以与按位OR组合。资源类型名称对调用模块而言是本地的。论证module_str尚未被使用,必须是NULLdtor可以是NULL如果不需要析构函数的话。

成功时,该函数返回一个指向资源类型的指针,并将*tried其设置为ERL_NIF_RT_CREATEERL_NIF_RT_TAKEOVER指示完成了什么。失败时,返回NULL并设置*triedflags。它可以设置triedNULL

请注意,enif_open_resource_type只允许在两个回调调用loadupgrade

另见enif_open_resource_type_x

ErlNifResourceType *enif_open_resource_type_x(ErlNifEnv* env, const char* name, const ErlNifResourceTypeInit* init, ErlNifResourceFlags flags, ErlNifResourceFlags* tried)

enif_open_resource_type除了接受与enif_selectand 一起使用的资源类型的附加回调函数外enif_monitor_process

论辩init是指向ErlNifResourceTypeInit结构,该结构包含析构函数、资源类型的向下回调和停止回调的函数指针。

int enif_port_command(ErlNifEnv* env, const ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg)

作为erlang:port_command/2,只是它总是完全异步的。

env调用过程的环境。一定不是NULL*to_port接收端口的端口号。端口ID是指本地节点上的端口。msg_env消息术语的环境。可以是与enif_alloc_envor 分配的与流程无关的环境NULLmsg要发送的消息条款。在有效载荷上也适用相同的限制erlang:port_command/2

使用msg_envNULL是一种优化,这组一起呼吁enif_alloc_envenif_make_copyenif_port_command,和enif_free_env成为一个呼叫。这种优化只有在大多数条款要从env中复制时才有用msg_env

回报true如果命令已成功发送。回报false如果命令失败,例如:

  • *to_port不引用本地端口。

  • 当前正在执行的进程%28,即发送方%29未激活。

  • msg是无效的。

另见enif_get_local_port

void *enif_priv_data(ErlNifEnv* env)

返回指向由loador 设置的私有数据的指针upgrade

ERL_NIF_TERM enif_raise_exception(ErlNifEnv* env, ERL_NIF_TERM reason)

使用术语创建错误异常。reason从nif返回,并将其与环境关联。env.一旦NIF或它调用的任何函数调用enif_raise_exception,运行时确保它创建的异常在NIF返回时引发,即使NIF试图返回一个非异常项。

的返回值。enif_raise_exception只能用作直接或间接调用它的NIF的返回值,或传递给enif_is_exception,但不适用于任何其他NIF API函数。

另见enif_has_pending_exceptionenif_make_badarg

int enif_realloc_binary(ErlNifBinary* bin, size_t size)

更改二进制文件的大小bin。源二进制文件可以是只读的,在这种情况下,它不会被触发,并且可变副本被分配并分配给它*bin

回报true关于成功,或false如果内存分配失败。

void enif_release_binary(ErlNifBinary* bin)

释放一个二进制文件enif_alloc_binary

void enif_release_resource(void* obj)

删除对从中obj获取的资源对象的引用enif_alloc_resource。当最后一个引用被删除时,资源对象被破坏。每个呼叫enif_release_resource必须对应于先前对enif_alloc_resource或的呼叫enif_keep_resource。所做的引用enif_make_resource只能由垃圾收集器删除。

ErlNifRWLock *enif_rwlock_create(char *name)

和...一样erl_drv_rwlock_create

void enif_rwlock_destroy(ErlNifRWLock *rwlck)

erl_drv_rwlock_destroy一样。

void enif_rwlock_rlock(ErlNifRWLock *rwlck)

erl_drv_rwlock_rlock一样。

void enif_rwlock_runlock(ErlNifRWLock *rwlck)

erl_drv_rwlock_runlock一样。

void enif_rwlock_rwlock(ErlNifRWLock *rwlck)

erl_drv_rwlock_rwlock一样。

void enif_rwlock_rwunlock(ErlNifRWLock *rwlck)

erl_drv_rwlock_rwlock一样。

int enif_rwlock_tryrlock(ErlNifRWLock *rwlck)

erl_drv_rwlock_tryrlock一样。

int enif_rwlock_tryrwlock(ErlNifRWLock *rwlck)

和erl_drv_rwlock_tryrlock一样。

ERL_NIF_TERM enif_schedule_nif(ErlNifEnv* env, const char* fun_name, int flags, ERL_NIF_TERM (*fp)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]), int argc, const ERL_NIF_TERM argv[])

附表NIFfp执行。此函数允许应用程序将长期运行的工作分解为多个常规的nif调用或调度dirty NIF若要在脏调度程序线程上执行,请执行以下操作。

fun_name

为计划执行的NIF提供名称。如果不能转换成原子,enif_schedule_nif返回badarg例外。

flags

必须设置为0普通的NIF。如果仿真器是在启用了脏调度程序支持的情况下生成的,flags可以设置为ERL_NIF_DIRTY_JOB_CPU_BOUND如果作业被期望是cpu绑定的,或者ERL_NIF_DIRTY_JOB_IO_BOUND对于那些将被I/O限制的工作。如果仿真程序中无法使用脏调度程序线程,则尝试调度这样的作业会导致notsup例外。

argcargv

可以是传递到调用NIF的原件,也可以是调用NIF创建的值。

调用NIF必须使用enif_schedule_nif作为它自己的返回值。

注意enif_schedule_nif顾名思义,只为以后的执行安排NIF。调用NIF不会阻止等待计划的NIF执行和返回。这意味着调用NIF不能期望接收计划的NIF返回值,并将其用于进一步的操作。

int enif_select(ErlNifEnv* env, ErlNifEvent event, enum ErlNifSelectFlags mode, void* obj, const ErlNifPid* pid, ERL_NIF_TERM ref)

当操作系统特定的事件对象准备好进行读或写操作时,此函数可用于接收异步通知。

论辩event标识事件对象。关于Unix系统,函数select/poll都是用的。事件对象必须是套接字、管道或其他文件描述符对象。select/poll可以用。

参数mode描述要等待的事件类型。它可以是ERL_NIF_SELECT_READERL_NIF_SELECT_WRITE或按位或组合件,等待两者。它也可以ERL_NIF_SELECT_STOP在下面进一步描述。当读或写事件被触发时,这样的通知消息被发送到由pid以下标识的过程:

{select, Obj, Ref, ready_input | ready_output}

ready_inputready_output指示事件对象是否已准备好进行读取或写入。

论辩pid可能是NULL若要指示调用进程,请执行以下操作。

参数obj是从中获得的资源对象enif_alloc_resource。资源对象的目的是作为事件对象的容器来管理其状态和生命周期。在通知消息中接收资源的句柄为Obj

论辩ref必须是从erlang:make_ref/0或者原子undefined.它将作为Ref在通知中。如果有选择性receive语句用于等待通知,然后在receive将利用运行时优化来绕过队列中所有先前接收的消息。

通知只是一次性的。要接收更多相同类型的通知(读或写),enif_select必须在收到每个通知后重复呼叫。

使用ERL_NIF_SELECT_STOPmode为了安全地关闭已传递到一个事件对象enif_select。当可以安全地关闭事件对象时,将调用stop资源的回调obj。即使已收到所有通知并且没有进一步的呼叫,enif_select也必须使用这种关闭事件对象的安全方式。

第一次呼叫enif_select对于特定的操作系统event将在事件对象和包含的资源之间建立关系。的所有后续调用event必须将其包含的资源作为参数传递。obj.关系在enif_select已被调用modeERL_NIF_SELECT_STOP以及相应的stop回调回来了。一个资源可以包含多个事件对象,但是一个事件对象只能包含在一个资源中。一种资源在其所包含的所有关系都被消除之前,是不会被摧毁的。

使用enif_monitor_process连同enif_select检测失败的Erlang进程并防止它们导致资源及其包含的OS事件对象的永久泄漏。

在成功时返回一个非负值,其中可以设置以下位数:

ERL_NIF_SELECT_STOP_CALLED停止回调被直接调用enif_selectERL_NIF_SELECT_STOP_SCHEDULED停止回调计划在某个其他线程上运行或稍后由此线程运行。

如果调用失败,可以设置折叠位,则返回一个负值:

ERL_NIF_SELECT_INVALID_EVENT论辩event不是有效的OS事件对象。ERL_NIF_SELECT_FAILED系统调用未能将事件对象添加到轮询集。

按位使用并测试返回值中的特定位。在未来的版本中可能会添加新的重要位,以便为失败的调用和成功的调用提供更详细的信息。不要使用类似于==,因为这可能导致应用程序停止工作。

例子:

retval = enif_select(env, fd, ERL_NIF_SELECT_STOP, resource, ref if (retval < 0) { /* handle error */ } /* Success! */ if (retval & ERL_NIF_SELECT_STOP_CALLED) { /* ... */ }

ErlNifPid *enif_self(ErlNifEnv* caller_env, ErlNifPid* pid)

初始化PID变量*pid若要表示调用进程,请执行以下操作。

回报pid...

int enif_send(ErlNifEnv* env, ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg)

向进程发送消息。

env调用进程的环境。一定是NULL只有当从创建的线程调用时。*to_pid接收过程的PID。PID是指本地节点上的进程。msg_env消息术语的环境。必须是与进程无关的环境。enif_alloc_env或者零。msg要发送的消息项。

回报true如果消息已成功发送。回报false如果发送操作失败,即:

  • *to_pid不引用活动的本地进程。

  • 当前正在执行的进程(即发件人)不活动。

msg_env所有条款(包括msg)的消息环境通过成功的呼叫而失效enif_send。环境要么被enif_free_env清理出来以便重用enif_clear_env

如果msg_env设置为NULLmsg术语被复制,调用后原始术语及其环境仍然有效。

当使用支持SMP的仿真器时,此函数才是线程安全的.。它只能用于来自NIF调用线程的非SMP仿真器.

通过msg_env作为NULL仅支持从ERTS 8.0(二郎/ OTP 19)。

unsigned enif_sizeof_resource(void* obj)

获取资源对象的字节大小obj而获得enif_alloc_resource

int enif_snprintf(char *str, size_t size, const char *format, ...)

类似于snprintf但是这个格式字符串也接受"%T",这是Erlang术语的格式。

void enif_system_info(ErlNifSysInfo *sys_info_ptr, size_t size)

driver_system_info一样。

int enif_term_to_binary(ErlNifEnv *env, ERL_NIF_TERM term, ErlNifBinary *bin)

分配一个新的二进制文件enif_alloc_binary并存储编码结果。term根据Erlang外部术语格式。

回报true关于成功,或false如果分配失败。

另见erlang:term_to_binary/1enif_binary_to_term

int enif_thread_create(char *name,ErlNifTid *tid,void * (*func)(void *),void *args,ErlNifThreadOpts *opts)

erl_drv_thread_create一样。

void enif_thread_exit(void *resp)

erl_drv_thread_exit一样。

int enif_thread_join(ErlNifTid, void **respp)

erl_drv_thread_join一样。

ErlNifThreadOpts *enif_thread_opts_create(char *name)

erl_drv_thread_opts_create一样。

void enif_thread_opts_destroy(ErlNifThreadOpts *opts)

erl_drv_thread_opts_destroy一样。

ErlNifTid enif_thread_self(void)

erl_drv_thread_self一样。

int enif_thread_type(void)

确定当前正在执行的线程的类型。正值表示调度程序线程,负值或零表示另一种线程。目前存在以下特定类型(将来可能会扩展):

ERL_NIF_THR_UNDEFINED

未定义的线程,它不是调度程序线程。

ERL_NIF_THR_NORMAL_SCHEDULER

一个正常的调度程序线程。

ERL_NIF_THR_DIRTY_CPU_SCHEDULER

脏CPU调度器线程。

ERL_NIF_THR_DIRTY_IO_SCHEDULER

一个脏的I/O调度器线程。

ErlNifTime enif_time_offset(ErlNifTimeUnit time_unit)

返回当前时间偏移Erlang monotonic timeErlang system time转换为time_unit作为论据通过。

time_unit返回值的时间单位。

回报ERL_NIF_TIME_ERROR如果使用无效的时间单元参数调用,或者从不是调度程序线程的线程调用。

另见ErlNifTimeErlNifTimeUnit

void *enif_tsd_get(ErlNifTSDKey key)

erl_drv_tsd_get一样。

int enif_tsd_key_create(char *name, ErlNifTSDKey *key)

erl_drv_tsd_key_create一样。

void enif_tsd_key_destroy(ErlNifTSDKey key)

erl_drv_tsd_key_destroy一样。

void enif_tsd_set(ErlNifTSDKey key, void *data)

erl_drv_tsd_set一样。

int enif_whereis_pid(ErlNifEnv *env, ERL_NIF_TERM name, ErlNifPid *pid)

使用已注册的名称查找进程。

env调用进程的环境。一定是NULL只有当从创建的线程调用时。name注册进程的名称,如原子。*pidErlNifPid其中存储解析的进程id。

关于成功,布景*pid注册的本地进程。name和回报true.如果name不是一个已注册的进程,也不是一个原子,false会被退回并且*pid没有变化。

作为erlang:whereis/1,但仅限于过程。见enif_whereis_port解析已注册的端口。

int enif_whereis_port(ErlNifEnv *env, ERL_NIF_TERM name, ErlNifPort *port)

以注册名称查找端口。

env调用进程的环境。一定是NULL只有当从创建的线程调用时。name注册端口的名称,如原子。*portErlNifPort其中存储解析端口id。

关于成功,布景*port注册的港口name和回报true.如果name不是注册端口,也不是原子,false会被退回并且*port没有变化。

作为erlang:whereis/1,但仅限于港口。见enif_whereis_pid解析已注册的进程。