我想更好地了解Erlang驱动程序是如何工作的,我从一本书中的一个简单示例开始,但是当我编译包含本机Erlang驱动程序代码的C文件时,我收到了以下编译错误消息:
/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;
}
答案 0 :(得分:1)
您的代码暗示您正在尝试构建链接的驱动程序。 此类驱动程序应编译为共享库documented 。如果您使用gcc,则需要传递-shared
和-fpic
。您从链接器获取未定义的引用错误这一事实表明您没有尝试构建共享库。
此处至少还有两个问题:
你书中的例子已经过时了。如果你使用相同版本的Erlang,这很好。如果您使用的是最新版本,则应参考the documentation。特别是,您的ErlDrvEntry
结构太小,因为它现在包含许多其他字段。
DRIVER_INIT
宏必须采用与driver_entry中的名称匹配的参数,如注释中所述。然而,代码中并非如此:名称为"example1_drv"
,而使用example_drv
调用宏。
此外,driver_free
现在(?)需要void*
并且演员阵容是多余的。