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向量。writev
I/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_send
和enif_port_command
也跌落时的发送过程是不是还活着。某些内部资源(如进程堆和进程控制块)的取消分配被延迟,直到肮脏的NIF完成。
初始化
ERL_NIF_INIT(MODULE, ErlNifFunc funcs[], load, NULL, upgrade, unload)
这是初始化NIF库的神奇宏。它将在全局文件范围内进行评估。
MODULE
Erlang模块的名称作为没有字符串引号的标识符。它被宏所束缚。
funcs
是该库中所有已实现的NIF的函数描述符的静态数组。
load
,upgrade
并且unload
是功能的指针。其中一个load
或被upgrade
称为初始化图书馆。unload
被称为释放图书馆。所有内容在下面分别介绍。
第四个参数NULL
被忽略。它早期用于reload
自OTP 20以来不再支持的deprecated 回调。
如果编译通过静态包含的NIF --enable-static-nifs
,则必须STATIC_ERLANG_NIF
在ERL_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
返回非0
。load
可以是,NULL
如果不需要初始化。
`int(升级)( ErlNifEnv env
,void priv_data,
void old_priv_data,ERL_NIF_TERM load_info)`
upgrade
在加载NIF库时调用,并且该模块的旧代码包含已加载的NIF库。
作为load
,除了*old_priv_data
已经包含最后一次调用load
或upgrade
为旧模块代码设置的值。*priv_data
被初始化为什么NULL
时候upgrade
被调用。它被允许写入两者*priv_data
和*old_priv_data.
该库无法加载,如果upgrade
返回其他任何东西0
或如果upgrade
是NULL
。
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_BOUND
或ERL_NIF_DIRTY_JOB_IO_BOUND
。
注
如果其中一个ERL_NIF_DIRTY_JOB_*_BOUND
设置标志,运行时系统不支持脏调度程序,运行时系统拒绝加载NIF库。
ErlNifBinary
typedef struct {
unsigned size;
unsigned char* data;
} ErlNifBinary;
ErlNifBinary
包含有关检查的二进制项的瞬态信息。data
的缓冲区的指针。size
具有二进制的原始内容的字节。
请注意,这ErlNifBinary
是一种半透明类型,您只能阅读字段size
和data
。
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
)相比,ErlNifPid
s是独立的,不受任何限制environment
。ErlNifPid
是一种不透明的类型。
ErlNifPort
一个端口标识符。与端口ID术语(实例ERL_NIF_TERM
)相比,ErlNifPort
s是独立的,不受任何限制environment
。ErlNifPort
是一种不透明的类型。
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_select
。obj
是资源,event
是操作系统事件,is_direct_call
如果调用是直接调用的,则为true;如果enif_select
调度是调度调用(可能来自另一个线程),则为false。
ErlNifCharEncoding
typedef enum {
ERL_NIF_LATIN1
}ErlNifCharEncoding;
字符串和原子中使用的字符编码。唯一支持的编码是ERL_NIF_LATIN1
ISO 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和WSASend
Win32上使用。它用在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
选项来配置一个ErlNifIOQueue
。ERL_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_binary
。ErlNifBinary
NIF呼叫之间可以保留一个已分配(和拥有)。
回报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
是无效的。
另见ErlNifBinaryToTerm
,erlang:binary_to_term/2
和enif_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
如果使用无效的时间单位参数调用。
另见ErlNifTime
和ErlNifTimeUnit
。
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
在由buf
size
指向的缓冲区中写入一个终止字符串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
在由buf
size
指向的缓冲区中写入一个终止字符串,该字符串由字符串中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
。如果reason
是NULL
指针,则忽略它。否则,如果与env
存在关联的未决异常设置*reason
为异常项的值。例如,如果enif_make_badarg
被调用来设置待处理的badarg
异常,则稍后调用enif_has_pending_exception(env, &reason)
设置*reason
为原子badarg
,然后返回true
。
另见enif_make_badarg
和enif_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函数返回之前,该内容是有效的。如果iovec
nif调用返回后应该是有效的,则可以在一个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)
将bin
进q
跳过第一个skip
字节。
回报true
关于成功,或false
如果skip
的大小大于bin
二进制数据的任何所有权都被转移到队列中,并且bin
将被认为是只读的,其余的NIF调用,然后作为释放。
int enif_ioq_enqv(ErlNifIOQueue *q, ErlNifIOVec *iovec, size_t skip)
将iovec
进q
跳过第一个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)
添加对资源对象的引用。obj
从enif_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
长度为字符串中创建一个原子项len
。NULL
字符被视为任何其他字符。如果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_exception
NIF,但不能传递给其他NIF API函数。
另见enif_has_pending_exception
和enif_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
,否则false
。false
如果长度name
超过原子允许的最大长度(255个字符),也会返回。
int enif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding encoding)
尝试从name
长度len
和编码的字符串中创建已有原子的术语encode
。NULL
字符被视为任何其他字符。
如果原子已经存在,则该函数将该项存储*atom
并返回true
,否则false
。false
如果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
和插入key
用value
。如果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_in
in *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
和替换旧的关联值key
与new_value
。
如果成功,此函数将设置*map_out
为新地图并返回true
。false
如果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)
创建由资源对象管理的内存的二进制术语。obj
由enif_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
和编码的字符的列表encoding
。NULL
字符被视为任何其他字符。
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
的参数数量(之后cnt
)ERL_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_POSITIVE
和ERL_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_FIRST
或ERL_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
如果使用无效的时间单元参数调用,或者从不是调度程序线程的线程调用。
另见ErlNifTime
和ErlNifTimeUnit
。
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
尚未被使用,必须是NULL
。dtor
可以是NULL
如果不需要析构函数的话。
成功时,该函数返回一个指向资源类型的指针,并将*tried
其设置为ERL_NIF_RT_CREATE
或ERL_NIF_RT_TAKEOVER
指示完成了什么。失败时,返回NULL
并设置*tried
为flags
。它可以设置tried
为NULL
。
请注意,enif_open_resource_type
只允许在两个回调调用load
和upgrade
。
另见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_select
and 一起使用的资源类型的附加回调函数外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_env
or 分配的与流程无关的环境NULL
。msg
要发送的消息条款。在有效载荷上也适用相同的限制erlang:port_command/2
。
使用msg_env
的NULL
是一种优化,这组一起呼吁enif_alloc_env
,enif_make_copy
,enif_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)
返回指向由load
or 设置的私有数据的指针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_exception
和enif_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
例外。
argc
和
argv
可以是传递到调用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_READ
,ERL_NIF_SELECT_WRITE
或按位或组合件,等待两者。它也可以ERL_NIF_SELECT_STOP
在下面进一步描述。当读或写事件被触发时,这样的通知消息被发送到由pid
以下标识的过程:
{select, Obj, Ref, ready_input | ready_output}
ready_input
或ready_output
指示事件对象是否已准备好进行读取或写入。
论辩pid
可能是NULL
若要指示调用进程,请执行以下操作。
参数obj
是从中获得的资源对象enif_alloc_resource
。资源对象的目的是作为事件对象的容器来管理其状态和生命周期。在通知消息中接收资源的句柄为Obj
。
论辩ref
必须是从erlang:make_ref/0
或者原子undefined
.它将作为Ref
在通知中。如果有选择性receive
语句用于等待通知,然后在receive
将利用运行时优化来绕过队列中所有先前接收的消息。
通知只是一次性的。要接收更多相同类型的通知(读或写),enif_select
必须在收到每个通知后重复呼叫。
使用ERL_NIF_SELECT_STOP
如mode
为了安全地关闭已传递到一个事件对象enif_select
。当可以安全地关闭事件对象时,将调用stop
资源的回调obj
。即使已收到所有通知并且没有进一步的呼叫,enif_select
也必须使用这种关闭事件对象的安全方式。
第一次呼叫enif_select
对于特定的操作系统event
将在事件对象和包含的资源之间建立关系。的所有后续调用event
必须将其包含的资源作为参数传递。obj
.关系在enif_select
已被调用mode
如ERL_NIF_SELECT_STOP
以及相应的stop
回调回来了。一个资源可以包含多个事件对象,但是一个事件对象只能包含在一个资源中。一种资源在其所包含的所有关系都被消除之前,是不会被摧毁的。
注
使用enif_monitor_process
连同enif_select
检测失败的Erlang进程并防止它们导致资源及其包含的OS事件对象的永久泄漏。
在成功时返回一个非负值,其中可以设置以下位数:
ERL_NIF_SELECT_STOP_CALLED
停止回调被直接调用enif_select
。ERL_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
设置为NULL
,msg
术语被复制,调用后原始术语及其环境仍然有效。
当使用支持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/1
和enif_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 time
和Erlang system time
转换为time_unit
作为论据通过。
time_unit
返回值的时间单位。
回报ERL_NIF_TIME_ERROR
如果使用无效的时间单元参数调用,或者从不是调度程序线程的线程调用。
另见ErlNifTime
和ErlNifTimeUnit
。
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
注册进程的名称,如原子。*pid
大ErlNifPid
其中存储解析的进程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
注册端口的名称,如原子。*port
大ErlNifPort
其中存储解析端口id。
关于成功,布景*port
注册的港口name
和回报true
.如果name
不是注册端口,也不是原子,false
会被退回并且*port
没有变化。
作为erlang:whereis/1
,但仅限于港口。见enif_whereis_pid
解析已注册的进程。