非常教程

Erlang 20参考手册

erl_interface

ei

C Library

ei

图书馆摘要

处理Erlang二进制术语格式的例程。

描述

图书馆ei包含宏和函数来编码和解码Erlang二进制术语格式。

ei允许您将二进制格式的原子,列表,数字和二进制文件转换为二进制格式。编写端口程序和驱动程序时这很有用。ei使用给定的缓冲区,没有动态内存(ei_decode_fun()除外),并且通常非常快。

ei还处理C节点、C程序,这些程序与Erlang节点%28或其他C节点%29使用Erlang分发格式讨论Erlang分发。之间的区别eierl_interface那是ei在发送和接收术语时直接使用二进制格式。它也是线程安全的,使用线程,一个进程可以处理多个C节点.。大erl_interface图书馆建在ei,但由于遗留原因,它不允许多个C节点。总的来说,ei是执行C节点的首选方法。

解码和编码函数使用缓冲区和索引到缓冲区中,这将指向编码和解码的位置。索引被更新到在术语编码/解码后立即指向。不检查该术语是否适合缓冲区。如果编码超出缓冲区,程序就会崩溃。

所有函数都有两个参数:

  • buf指向二进制数据所在的缓冲区的指针。
  • index指向缓冲区的索引的指针。此参数随解码/编码术语的大小而递增。

这些数据因此在调用函数buf[*index]时发生ei

所有编码函数都假定bufindex参数指向足以容纳数据的缓冲区。若要获取编码项的大小,而不对其进行编码,请传递NULL而不是缓冲区指针。参数index是递增的,但是没有编码。这就是进来的路ei到“飞行前”术语编码。

还有使用动态缓冲区的编码函数。使用这些来编码数据通常更方便。所有的编码函数都有两个版本;第一个版本是ei_x使用动态缓冲区。

如果成功,所有函数都会返回0,否则返回-1(例如,如果一个术语不是预期的类型,或者要解码的数据是一个无效的Erlang术语)。

某些解码功能需要预先分配的缓冲区。此缓冲区必须足够大,对于非复合类型,ei_get_type()函数返回所需的大小(请注意,对于字符串,需要额外的字节用于NULL-terminator)。

数据类型

erlang_char_encoding

typedef enum {
    ERLANG_ASCII = 1,
    ERLANG_LATIN1 = 2,
    ERLANG_UTF8 = 4
} erlang_char_encoding;

用于原子的字符编码。ERLANG_ASCII代表7位ASCII码。Latin-1和UTF-8是7位ASCII的不同扩展名。所有7位ASCII字符都是有效的Latin-1和UTF-8字符。ASCII和Latin-1都代表每个字符一个字节。一个UTF-8字符可以由1-4个字节组成。请注意,这些常量是位标志,可以按位或组合。

输出

int ei_decode_atom(const char *buf, int *index, char *p)

从二进制格式解码原子。NULL原子的终止名称被放置在p。最多的MAXATOMLEN字节可以放在缓冲区中。

int ei_decode_atom_as(const char *buf, int *index, char *p, int plen, erlang_char_encoding want, erlang_char_encoding* was, erlang_char_encoding* result)

从二进制格式解码原子。NULL原子的终止名称被放置在p长度为plen字节的缓冲区中。

想要的字符串编码由want指定。 二进制格式(Latin-1或UTF-8)中使用的原始编码可以从*获得。 结果字符串的编码(7位ASCII,Latin-1或UTF-8)可以从*结果中获得。 两者都是和结果可以是NULL。 如果want是像ERLANG_LATIN1 | ERLANG_UTF8那样的按位OR'd组合,或者如果*结果是纯7位ASCII(兼容Latin-1和UTF-8),则结果可能与预期不同。

如果原子对于缓冲区太长或者无法用编码想要表示,则此函数失败。

这个函数在Erlang / OTP R16中引入,作为支持UTF-8原子的第一步的一部分。

int ei_decode_bignum(const char *buf, int *index, mpz_t obj)

将二进制格式的整数解码为GMP mpz_t整数。 要使用此功能,必须配置和编译ei库以使用GMP库。

int ei_decode_binary(const char *buf, int *index, void *p, long *len)

从二进制格式解码二进制文件。参数len设置为二进制文件的实际大小。注意,ei_decode_binary()假设二进制文件有足够的空间。所需的大小可以通过ei_get_type()

int ei_decode_boolean(const char *buf, int *index, int *p)

从二进制格式解码布尔值。 布尔实际上是一个原子,真解码1和假解码0。

int ei_decode_char(const char *buf, int *index, char *p)

从二进制格式解码0-255之间的char(8位)整数。由于历史原因,返回的整数是类型的charunsigned char即使C编译器和系统可以定义char为被签名,您的C代码也会将返回的值视为类型。

int ei_decode_double(const char *buf, int *index, double *p)

从二进制格式解码双精度(64位)浮点数。

int ei_decode_ei_term(const char* buf, int* index, ei_term* term)

解码任何术语,或者至少尝试。 如果buf中的*索引指向的术语适合术语联合,则将其解码,并设置术语 - >值中的适当字段,并且*索引增加术语大小。

该函数在成功解码时返回1,错误时返回-1,如果该术语看起来没问题,则返回0,但不适合术语结构。 如果返回1,则索引增加,并且项包含解码后的项。

term结构包含元组或列表的元素,二进制,字符串或原子的大小。它包含一个术语,如果它是以下任何一个术语:整数,浮点数,原子,pid,端口或参考。

int ei_decode_fun(const char *buf, int *index, erlang_fun *p)void free_fun(erlang_fun* f)

从二进制格式解码一个乐趣。 参数p是NULL或指向erlang_fun结构。 这是分配内存的唯一解码功能。 当不再需要erlang_fun时,它将被free_fun释放。 (这与有趣的环境的任意大小有关。)

int ei_decode_list_header(const char *buf, int *index, int *arity)

从二进制格式解码列表标题。 元素的数量返回arity。 元素+ 1元素跟随(最后一个是列表的尾部,通常是一个空列表)。 如果arity为0,则它是一个空列表。

请注意,如果列表完全由范围为0到255的整数组成,则列表将被编码为字符串。这个函数不会解码这些字符串,而是使用ei_decode_string()

int ei_decode_long(const char *buf, int *index, long *p)

从二进制格式解码长整数。如果代码是64位,则函数ei_decode_long()类似于ei_decode_longlong()...

int ei_decode_longlong(const char *buf, int *index, long long *p)

从二进制格式解码GCC long long或Visual C ++ __int64(64位)整数。该功能在VxWorks端口中缺失。

int ei_decode_map_header(const char *buf, int *index, int *arity)

从二进制格式解码地图标题。键值对的数量返回*arity。键和值按照以下顺序排列:K1, V1, K2, V2, ..., Kn, Vn。这使得arity*2条款总数。如果arity为零,则它是空的地图。正确编码的地图不具有重复的键。

int ei_decode_pid(const char *buf, int *index, erlang_pid *p)

从二进制格式解码进程标识符(pid)。

int ei_decode_port(const char *buf, int *index, erlang_port *p)

从二进制格式解码端口标识符。

int ei_decode_ref(const char *buf, int *index, erlang_ref *p)

从二进制格式解码引用。

int ei_decode_string(const char *buf, int *index, char *p)

从二进制格式解码字符串。Erlang中的字符串是0到255之间的整数列表。请注意,由于字符串只是一个列表,因此有时列表会被编码为字符串term_to_binary/1,即使它不是有意的。

该字符串被复制到p,并且必须分配足够的空间。返回的字符串被NULL终止,所以您必须为内存需求添加一个额外的字节。

int ei_decode_term(const char *buf, int *index, void *t)

从二进制格式解码术语。 该术语作为ETERM *返回t,因此t实际上是ETERM **(请参阅erl_eterm)。 该术语稍后将被释放。

注意这个函数位于Erl_Interface库中。

int ei_decode_trace(const char *buf, int *index, erlang_trace *p)

从二进制格式解码Erlang跟踪令牌。

int ei_decode_tuple_header(const char *buf, int *index, int *arity)

解码元组头,元素的数量返回arity。元组元素在缓冲区中按顺序排列。

int ei_decode_ulong(const char *buf, int *index, unsigned long *p)

从二进制格式解码无符号长整数。如果代码是64位,则函数ei_decode_ulong()类似于ei_decode_ulonglong()...

int ei_decode_ulonglong(const char *buf, int *index, unsigned long long *p)

从二进制格式解码GCC无符号long long或Visual C ++无符号__int64(64位)整数。 该功能在VxWorks端口中缺失。

int ei_decode_version(const char *buf, int *index, int *version)

解码Erlang二进制术语格式的版本幻数。它必须是二进制术语中的第一个标记。

int ei_encode_atom(char *buf, int *index, const char *p)int ei_encode_atom_len(char *buf, int *index, const char *p, int len)int ei_x_encode_atom(ei_x_buff* x, const char *p)int ei_x_encode_atom_len(ei_x_buff* x, const char *p, int len)

以二进制格式编码原子。参数p是Latin-1编码中原子的名称。只有最多MAXATOMLEN-1字节被编码。该名称将被NULL终止,除了该ei_x_encode_atom_len()功能。

int ei_encode_atom_as(char *buf, int *index, const char *p, erlang_char_encoding from_enc, erlang_char_encoding to_enc)int ei_encode_atom_len_as(char *buf, int *index, const char *p, int len, erlang_char_encoding from_enc, erlang_char_encoding to_enc)int ei_x_encode_atom_as(ei_x_buff* x, const char *p, erlang_char_encoding from_enc, erlang_char_encoding to_enc)int ei_x_encode_atom_len_as(ei_x_buff* x, const char *p, int len, erlang_char_encoding from_enc, erlang_char_encoding to_enc)

以二进制格式编码原子。Parameter p是具有字符编码的原子的名称from_enc(ASCII,Latin-1或UTF-8)。该名称必须被NULL终止,或者len必须使用带参数的函数变体。

如果p在编码中不是有效的字符串,则编码from_enc将失败。

论据to_enc被忽略。从Erlang / OTP 20开始,编码总是以UTF-8格式完成,这种格式可以像Erlang / OTP R16一样陈旧。

int ei_encode_bignum(char *buf, int *index, mpz_t obj)int ei_x_encode_bignum(ei_x_buff *x, mpz_t obj)

将GMP mpz_t整数编码为二进制格式。要使用此功能,ei必须对库进行配置和编译以使用GMP库。

int ei_encode_binary(char *buf, int *index, const void *p, long len)int ei_x_encode_binary(ei_x_buff* x, const void *p, long len)

以二进制格式编码二进制文件。的数据是在p,的len字节长度。

int ei_encode_boolean(char *buf, int *index, int p)int ei_x_encode_boolean(ei_x_buff* x, int p)

如果p不为零,则将布尔值编码为原子真;如果p为零,则将其编码为假。

int ei_encode_char(char *buf, int *index, char p)int ei_x_encode_char(ei_x_buff* x, char p)

以二进制格式的0-255之间的整数对char(8位)进行编码。 由于历史原因,整数参数是char类型。 即使C编译器和系统可能定义要被签名的char,你的C代码也会将指定的参数视为unsigned char类型。

int ei_encode_double(char *buf, int *index, double p)int ei_x_encode_double(ei_x_buff* x, double p)

以二进制格式编码双精度(64位)浮点数。

如果浮点数不是有限的,则返回-1

int ei_encode_empty_list(char* buf, int* index)int ei_x_encode_empty_list(ei_x_buff* x)

对空列表进行编码。它经常在列表的尾部使用。

int ei_encode_fun(char *buf, int *index, const erlang_fun *p)int ei_x_encode_fun(ei_x_buff* x, const erlang_fun* fun)

以二进制格式编码一个乐趣。 参数p指向erlang_fun结构。 erlang_fun不会自动释放,如果编码后不需要fun,则会调用free_fun。

int ei_encode_list_header(char *buf, int *index, int arity)int ei_x_encode_list_header(ei_x_buff* x, int arity)

使用指定的元素编码列表标题。接下来的arity+1术语是元素(实际上是它的aritycons单元)和列表的尾部。列表和元组是递归编码的,所以列表可以包含另一个列表或元组。

例如,要对列表[c, d, [e | f]]进行编码:

ei_encode_list_header(buf, &i, 3);
ei_encode_atom(buf, &i, "c");
ei_encode_atom(buf, &i, "d");
ei_encode_list_header(buf, &i, 1);
ei_encode_atom(buf, &i, "e");
ei_encode_atom(buf, &i, "f");
ei_encode_empty_list(buf, &i);

似乎没有办法在事先不知道元素数量的情况下创建列表。但确实有办法。注意列表[a, b, c]可以写成[a | [b | [c]]]。使用这个,列表可以写成conses。

对列表进行编码,而事先不知道其重要性:

while (something()) {
    ei_x_encode_list_header(&x, 1);
    ei_x_encode_ulong(&x, i); /* just an example */
}
ei_x_encode_empty_list(&x);

int ei_encode_long(char *buf, int *index, long p)int ei_x_encode_long(ei_x_buff* x, long p)

以二进制格式编码长整数。如果代码是64位,则函数ei_encode_long()类似于ei_encode_longlong()...

int ei_encode_longlong(char *buf, int *index, long long p)int ei_x_encode_longlong(ei_x_buff* x, long long p)

以二进制格式编码GCC long long或Visual C ++ __int64(64位)整数。该功能在VxWorks端口中缺失。

int ei_encode_map_header(char *buf, int *index, int arity)int ei_x_encode_map_header(ei_x_buff* x, int arity)

使用指定的arity编码地图标题。 下一个编码的* 2项将是按以下顺序编码的映射的键和值:K1,V1,K2,V2,...,Kn,Vn。

例如,要编码map#{a => "Apple", b => "Banana"}

ei_x_encode_map_header(&x, 2);
ei_x_encode_atom(&x, "a");
ei_x_encode_string(&x, "Apple");
ei_x_encode_atom(&x, "b");
ei_x_encode_string(&x, "Banana");

正确编码的映射不能有重复的键。

int ei_encode_pid(char *buf, int *index, const erlang_pid *p)int ei_x_encode_pid(ei_x_buff* x, const erlang_pid *p)

以二进制格式编码Erlang进程标识符(pid)。参数p指向一个erlang_pid结构(应该在之前获得ei_decode_pid())。

int ei_encode_port(char *buf, int *index, const erlang_port *p)int ei_x_encode_port(ei_x_buff* x, const erlang_port *p)

以二进制格式编码Erlang端口。参数p指向一个erlang_port结构(应该在之前获得ei_decode_port())。

int ei_encode_ref(char *buf, int *index, const erlang_ref *p)int ei_x_encode_ref(ei_x_buff* x, const erlang_ref *p)

以二进制格式编码Erlang参考。参数p指向一个erlang_ref结构(应该在之前获得ei_decode_ref())。

int ei_encode_string(char *buf, int *index, const char *p)int ei_encode_string_len(char *buf, int *index, const char *p, int len)int ei_x_encode_string(ei_x_buff* x, const char *p)int ei_x_encode_string_len(ei_x_buff* x, const char* s, int len)

以二进制格式编码字符串。(Erlang中的字符串是一个列表,但被编码为二进制格式的字符数组。)该字符串将被NULL终止,但该ei_x_encode_string_len()函数除外。

int ei_encode_term(char *buf, int *index, void *t)int ei_x_encode_term(ei_x_buff* x, void *t)

编码一个ETERM,从中获得erl_interface。参数t实际上是一个ETERM指针。此功能不释放ETERM

int ei_encode_trace(char *buf, int *index, const erlang_trace *p)int ei_x_encode_trace(ei_x_buff* x, const erlang_trace *p)

以二进制格式编码Erlang跟踪令牌。参数p指向一个erlang_trace结构(应该在之前获得ei_decode_trace())。

int ei_encode_tuple_header(char *buf, int *index, int arity)int ei_x_encode_tuple_header(ei_x_buff* x, int arity)

编码具有指定元素的元组标题。接下来arity编码的术语将是元组的元素。元组和列表是递归编码的,所以元组可以包含另一个元组或列表。

例如,对元组进行编码。{a, {b, {}}}*

ei_encode_tuple_header(buf, &i, 2);
ei_encode_atom(buf, &i, "a");
ei_encode_tuple_header(buf, &i, 2);
ei_encode_atom(buf, &i, "b");
ei_encode_tuple_header(buf, &i, 0);

int ei_encode_ulong(char *buf, int *index, unsigned long p)int ei_x_encode_ulong(ei_x_buff* x, unsigned long p)

以二进制格式对无符号长整数进行编码。如果代码是64位,则函数ei_encode_ulong()类似于ei_encode_ulonglong()...

int ei_encode_ulonglong(char *buf, int *index, unsigned long long p)int ei_x_encode_ulonglong(ei_x_buff* x, unsigned long long p)

以二进制格式编码GCC unsigned long long或Visual C ++ unsigned __int64(64位)整数。该功能在VxWorks端口中缺失。

int ei_encode_version(char *buf, int *index)int ei_x_encode_version(ei_x_buff* x)

编码二进制格式的版本数。必须是二进制术语中的第一个标记。

int ei_get_type(const char *buf, const int *index, int *type, int *size)

返回编码术语大小的类型和大小。 对于字符串和原子,大小是不包括终止NULL的字符数。 对于二进制文件,大小是字节数。 对于列表和元组,大小是对象的arity。 对于其他类型,大小为0.在所有情况下,索引保持不变。

int ei_print_term(FILE* fp, const char* buf, int* index)int ei_s_print_term(char** s, const char* buf, int* index)

以明文形式将术语打印到指定的文件fp或指向的缓冲区s。它试图类似于在Erlang shell中打印的术语。

ei_s_print_term(),参数s是指向一个动态(malloc)分配的BUFSIZ字节串或一个NULL指针。*s如果结果多于BUFSIZ字符,则可以通过此函数重新分配字符串(并可进行更新)。返回的字符串被NULL终止。

返回值是写入文件或字符串的字符数,如果buf [index]不包含有效的项,则返回-1。 不幸的是,fp上的I / O错误没有被检查。

参数index被更新,也就是说,这个函数可以被看作是一个解码函数,它将一个术语解码为一个可读的格式。

void ei_set_compat_rel(release_number)

类型

默认情况下,ei库只能保证与ei库本身的相同版本中的其他Erlang / OTP组件兼容。 例如,来自Erlang / OTP R10的ei默认与Erlang / OTP R9的Erlang仿真器不兼容。

调用ei_set_compat_rel(release_number)ei库设置为发布的兼容模式release_number。有效范围release_number[7, current release]。这使得与早期版本的Erlang / OTP组件进行通信成为可能。

如果这个函数被调用,它只能被调用一次,并且必须在ei库中的任何其他函数被调用之前被调用。

警告

如果不小心使用此功能,您可能会遇到麻烦。始终确保所有通信组件要么来自同一个Erlang/OTP版本,要么来自X版和Y版,其中Y版的所有组件都处于X版的兼容模式。

int ei_skip_term(const char* buf, int* index)

跳过指定缓冲区中的术语;递归跳过列表和元组的元素,从而跳过整个术语。这是获取Erlang项大小的一种方法。

buf是缓冲区。

index更新为在缓冲区中的术语后面指向。

当您想要持有任意的术语时,这可能很有用:跳过它们并将二进制术语数据复制到某个缓冲区。

成功时返回 0,否则返回-1

int ei_x_append(ei_x_buff* x, const ei_x_buff* x2)int ei_x_append_buf(ei_x_buff* x, const char* buf, int len)

在缓冲区末尾追加数据。x...

int ei_x_format(ei_x_buff* x, const char* fmt, ...)int ei_x_format_wo_ver(ei_x_buff* x, const char *fmt, ... )

将一个词作为字符串格式化为一个缓冲区。 用于Erlang条款的sprintf。 fmt包含一个格式字符串,带有像〜d这样的参数,用于从变量中插入术语。 支持以下格式(给出C类型):

~a  An atom, char*
~c  A character, char
~s  A string, char*
~i  An integer, int
~l  A long integer, long int
~u  A unsigned long integer, unsigned long int
~f  A float, float
~d  A double float, double float
~p  An Erlang pid, erlang_pid*

例如,要用以下内容对元组进行编码:

ei_x_format("{~a,~i,~d}", "numbers", 12, 3.14159)
encodes the tuple {numbers,12,3.14159}

ei_x_format_wo_ver()格式设置为缓冲区,而不使用初始版本字节。

int ei_x_free(ei_x_buff* x)

解放ei_x_buff缓冲器。缓冲区使用的内存返回到操作系统。

int ei_x_new(ei_x_buff* x)int ei_x_new_with_version(ei_x_buff* x)

分配一个新的ei_x_buff缓冲区。由参数指向的结构的字段x被填充,并且分配默认缓冲区。ei_x_new_with_version()还会放入一个初始版本字节,该字节以二进制格式使用(所以ei_x_encode_version()不需要)。

调试信息

在模拟器似乎没有接收到您发送的条件时检查哪些内容的一些提示:

  • 请小心使用版本标题,且ei_x_new_with_version()在适当时使用。
  • 打开Erlang节点上的分布跟踪。
  • 检查结果代码ei_decode_-calls...

另见

erl_eterm

Erlang 20

Erlang 是一种通用的面向并发的编程语言,可应付大规模开发活动的程序设计语言和运行环境。

主页 https://www.erlang.org/
源码 https://github.com/erlang/otp
版本 20
发布版本 20.1