Как скомпилировать драйвер Erlang?
Я пытаюсь лучше понять, как работают драйверы Erlang, и я начал с простого примера из книги, но когда я начал компилировать файл C, содержащий исходный код драйвера Erlang, я получил следующие сообщения об ошибках компиляции:
/tmp/ccQ0GroH.o:example1_lid.c:(.text+0xe): неопределенная ссылка на
driver_alloc' /tmp/ccQ0GroH.o:example1_lid.c:(.text+0x2f): undefined reference to
driver_free' /tmp/ccQ0GroH.o:example1_lid.c:(.text+0xb0): неопределенная ссылка на `driver_output'
Кто-нибудь знает, почему это может происходить и как я могу это исправить? Файл C размещен ниже для справки.
Благодарю.
/* example1_lid.c */
#include <stdio.h>
#include "erl_driver.h"
typedef struct {
ErlDrvPort port;
} example_data;
static ErlDrvData example_drv_start(ErlDrvPort port, char *buff)
{
example_data* d = (example_data*)driver_alloc(sizeof(example_data));
d->port = port;
return (ErlDrvData)d;
}
static void example_drv_stop(ErlDrvData handle)
{
driver_free((char*)handle);
}
static void example_drv_output(ErlDrvData handle, char *buff, int bufflen)
{
example_data* d = (example_data*)handle;
char fn = buff[0], arg = buff[1], res;
if (fn == 1) {
res = twice(arg);
} else if (fn == 2) {
res = sum(buff[1], buff[2]);
}
driver_output(d->port, &res, 1);
}
ErlDrvEntry example_driver_entry = {
NULL, /* F_PTR init, N/A */
example_drv_start, /* L_PTR start, called when port is opened */
example_drv_stop, /* F_PTR stop, called when port is closed */
example_drv_output, /* F_PTR output, called when erlang has sent
data to the port */
NULL, /* F_PTR ready_input,
called when input descriptor ready to read*/
NULL, /* F_PTR ready_output,
called when output descriptor ready to write */
"example1_drv", /* char *driver_name, the argument to open_port */
NULL, /* F_PTR finish, called when unloaded */
NULL, /* F_PTR control, port_command callback */
NULL, /* F_PTR timeout, reserved */
NULL /* F_PTR outputv, reserved */
};
DRIVER_INIT(example_drv) /* must match name in driver_entry */
{
return &example_driver_entry;
}
1 ответ
Ваш код подразумевает, что вы пытаетесь создать связанный драйвер. Такие драйверы должны быть скомпилированы как общие библиотеки, как описано в документации. Если вы используете gcc, вам нужно пройти -shared
а также -fpic
, Тот факт, что вы получаете неопределенную ошибку ссылки от компоновщика, говорит о том, что вы не пытаетесь создать общую библиотеку.
Здесь есть как минимум две дополнительные проблемы:
Пример в вашей книге довольно устарел. Это хорошо, если вы используете ту же версию Erlang. Если вы используете последнюю версию, вам следует обратиться к документации. В частности, ваш
ErlDrvEntry
структура слишком мала, так как теперь она включает в себя множество других полей.DRIVER_INIT
макрос должен принимать аргумент, который должен совпадать с именем в driver_entry, как указано в комментарии. Тем не менее, это не так в коде: имя"example1_drv"
в то время как макрос вызывается сexample_drv
,
Дополнительно, driver_free
сейчас (?) занимает void*
и актёрский состав лишний.