tags:

views:

193

answers:

3

I've got a bare-minimum Erlang port driver:

erl_driver_bridge.c -> erl_driver_bridge.dll

#define __WIN32__

#include "erl_driver.h"

typedef struct {
    ErlDrvPort port;
} erl_driver_bridge_data;

static ErlDrvData bridge_start(ErlDrvPort port, char *buff) {
    erl_driver_bridge_data* d =
        (erl_driver_bridge_data*)driver_alloc(sizeof(erl_driver_bridge_data));
    d->port = port;
    return (ErlDrvData)d;
}

static void bridge_stop(ErlDrvData data) {
    driver_free((char*)data);
}

static void bridge_output(ErlDrvData data, char *buff, int bufflen) {
    erl_driver_bridge_data* d = (erl_driver_bridge_data*)data;
}

ErlDrvEntry erl_driver_bridge_entry = {
    NULL,               /* F_PTR init, N/A */
    bridge_start,    /* L_PTR start, called when port is opened */
    bridge_stop,     /* F_PTR stop, called when port is closed */
    bridge_output,      /* F_PTR output, called when erlang has sent */
    NULL,               /* F_PTR ready_input */
    NULL,               /* F_PTR ready_output */
    "erl_driver_bridge", /* char *driver_name, the argument to open_port */
    NULL,               /* F_PTR finish, called when unloaded */
    NULL,               /* Not used */
    NULL,      /* F_PTR control, port_command callback */
    NULL,               /* F_PTR timeout, reserved */
    NULL,               /* F_PTR outputv, reserved */
    NULL,               /* F_PTR ready_async */
    NULL,               /* F_PTR flush */
    NULL,               /* F_PTR call */
    NULL,               /* F_PTR event */
    ERL_DRV_EXTENDED_MARKER,
    ERL_DRV_EXTENDED_MAJOR_VERSION,
    ERL_DRV_EXTENDED_MINOR_VERSION,
    0,
    NULL,               /* Reserved -- Used by emulator internally */
    NULL,               /* F_PTR process_exit */
};

DRIVER_INIT(erl_driver_bridge) {
    return &erl_driver_bridge_entry;
}

Then I try to load it in Erlang:

case erl_ddll:load_driver(".", erl_driver_bridge) of
    ok -> ok;
    {error, Error} -> erl_ddll:format_error(Error)
end.

Which produces:

The specified module could not be found.

I've checked that the driver exists in the current directory and even specified the full path, but Erlang still doesn't see it. Any ideas?

+1  A: 

On Windows, the extension of the file should be ddl, not dll ?

Alan Moore
You're right, I missed that part of the documentation. Unfortunately, it still won't load. Although this time, the error code is -136 rather than -167, but format_error still returns "The specified module could not be found." :(
David Brown
Download this utility and use it to try and load your file - http://www.dependencywalker.com/ - it should show what other files you are dependent on and whether your library can actually be loaded or not. You may find from that that you're missing another dependent dll...
Alan Moore
It was missing MSVCR90.dll, so I compiled with the /MT flag and now Dependency Walker reports no errors. However, Erlang still refuses to load it.
David Brown
Have you tried putting in the full path instead of just "." ?
Alan Moore
If I'm reading the erts win32 source correctly it looks like the documentation is incorrect and the extension should be dll... So maybe your change to the dependency and then a change back to dll might help (and then maybe the full path if needed)
Alan Moore
@Alan: Yep, that was it. Changing it to back to .DLL worked like a charm. I really wish the Erlang team would fix up their docs. I'm seeing conflicting information all over the place.
David Brown
A: 

Comparing yours to my bare-minimum one, which I hacked a while ago. Might help, might not help...

  • I also included ei.h

  • I declared ErlDrvEntry erl_driver_bridge_entry static

Zed
+1  A: 

You should probably use 'file:get_cwd' to get the current working directory first and append your path next.

Also handy but probably unrelated to your current question: have you checked the code path that the Erlang emulator uses? Use the function 'code:get_path' (http://www.erlang.org/doc/man/code.html) to inspect the search path. You can use 'code:add_path' to insert paths conveniently.

jldupont