如何编译 Erlang 驱动程序?

Posted

技术标签:

【中文标题】如何编译 Erlang 驱动程序?【英文标题】:How to compile an Erlang driver? 【发布时间】:2013-10-17 11:57:03 【问题描述】:

我试图更好地理解 Erlang 驱动程序的工作原理,我从书中的一个简单示例开始,但是当我编译包含本机 Erlang 驱动程序代码的 C 文件时,我收到以下编译错误消息:

/tmp/ccQ0GroH.o:example1_lid.c:(.text+0xe): 未定义引用driver_alloc' /tmp/ccQ0GroH.o:example1_lid.c:(.text+0x2f): undefined reference todriver_free' /tmp/ccQ0GroH.o:example1_lid.c:(.text+0xb0): undefined reference to `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】:

您的代码暗示您正在尝试构建链接的驱动程序。 此类驱动程序应编译为documented 的共享库。如果使用 gcc,则需要传递 -shared-fpic。您从链接器收到未定义的引用错误这一事实表明您没有尝试构建共享库。

这里至少还有两个额外的问题:

    您书中的示例已经过时了。如果您使用的是相同版本的 Erlang,这很好。如果您使用的是最新版本,请参考the documentation。特别是您的 ErlDrvEntry 结构太小,因为它现在包含许多其他字段。

    DRIVER_INIT 宏必须采用与 driver_entry 中的名称匹配的参数,如注释中所述。然而,代码中的情况并非如此:名称是"example1_drv",而宏是用example_drv 调用的。

此外,driver_free 现在 (?) 需要 void* 并且演员表是多余的。

【讨论】:

以上是关于如何编译 Erlang 驱动程序?的主要内容,如果未能解决你的问题,请参考以下文章

加快 Erlang 的编辑、编译、运行/调试周期

混合编译过程的程序路径

初见Erlang交互式环境

为何编程如此之难?Erlang 之父的感触

erlang虚拟机代码运行原理

erlang虚拟机代码执行原理