Erlang – мощный язык программирования, известный своей параллелизмом и отказоустойчивостью. Одной из ключевых особенностей Erlang является его способность взаимодействовать с внешними программами через порты. В этой статье мы рассмотрим различные методы связи портов в Erlang и предоставим примеры кода для демонстрации каждого подхода.
Метод 1: использование драйвера порта
Erlang предоставляет интерфейс драйвера порта, который позволяет вам писать собственные драйверы на C или C++ для взаимодействия с внешними программами. Вот пример простого драйвера порта на C:
#include "erl_driver.h"
static ErlDrvData start(ErlDrvPort port, char* cmd)
{
// Initialization code
return NULL;
}
static void stop(ErlDrvData data)
{
// Cleanup code
}
static void process(ErlDrvData data, ErlIOVec* ev)
{
// Handle incoming messages from Erlang
}
ErlDrvEntry port_driver_entry = {
NULL, /* F_PTR init, called when driver is loaded */
start, /* L_PTR start, called when port is opened */
stop, /* F_PTR stop, called when port is closed */
NULL, /* F_PTR output, called when Erlang has sent */
NULL, /* F_PTR ready_input, called when input descriptor ready */
NULL, /* F_PTR ready_output, called when output descriptor ready */
"my_port_drv", /* char *driver_name, the argument to open_port */
NULL, /* F_PTR finish, called when unloaded */
NULL, /* void *handle, Reserved by VM */
process, /* F_PTR control, port_command callback */
NULL, /* F_PTR timeout, reserved */
NULL, /* F_PTR outputv, reserved */
NULL, /* F_PTR ready_async, only for async drivers */
NULL, /* F_PTR flush, called when port is about
to be closed, but there is data in driver
queue */
NULL, /* F_PTR call, much like control, sync call
to driver */
NULL, /* F_PTR event, called when an event selected
by driver_event() occurs. */
ERL_DRV_EXTENDED_MARKER,
ERL_DRV_EXTENDED_MAJOR_VERSION,
ERL_DRV_EXTENDED_MINOR_VERSION,
ERL_DRV_FLAG_USE_PORT_LOCKING,
NULL, /* Reserved */
NULL, /* F_PTR process_exit, called when a process
monitored by a driver dies */
};
DRIVER_INIT(my_port_drv)
{
return &port_driver_entry;
}
Метод 2: использование функции open_port
Erlang предоставляет функцию open_port
, которая позволяет выполнять внешние программы и взаимодействовать с ними посредством стандартного ввода и вывода. Вот пример:
{ok, Port} = open_port({spawn, "my_program"}, [stream]),
Port ! {self(), {command, "Hello"}},
receive
{Port, {data, Data}} -> io:format("Received: ~p~n", [Data])
end,
Port ! {self(), close}.
Метод 3: использование модуля erl_interface
Модуль erl_interface
предоставляет функции для связи с узлами Erlang с использованием внешнего формата терминов Erlang (ETF). Вы можете использовать этот модуль для установления связи между Erlang и внешними программами. Вот пример:
{ok, Port} = erl_interface:connect("localhost", 1234),
erl_interface:send(Port, {self(), {command, "Hello"}}),
receive
{Port, {data, Data}} -> io:format("Received: ~p~n", [Data])
end,
erl_interface:close(Port).
В этой статье мы рассмотрели различные методы связи портов в Erlang. Мы рассмотрели использование драйверов портов, функции open_port
и модуля erl_interface
. Каждый метод обеспечивает разные уровни гибкости и контроля над процессом связи. Используя эти методы, вы можете легко интегрировать Erlang с внешними программами и построить надежные распределенные системы.