driver_output_term() and unsigned long (32 bit) values

Scott Lystig Fritchie fritchie@REDACTED
Sat Jul 27 01:10:15 CEST 2002


>>>>> "sp" == Shawn Pearce <spearce@REDACTED> writes:

sp> I had really considered making a bunch of ErlDrvBinary objects in
sp> a mmap region at one point, until I noticed in the Erts source
sp> that the ErlDrvBinary is not the entire binary structure - there
sp> is data stored before it by the emulator.  I would have had pretty
sp> ugly results had I tried to use my own binary.

If it's any help, here are some snippets from my Erlang Driver Tool
Kit.  I cooked up some quickie replacements for malloc(), realloc(),
and free() as well as a function (could be a macro, I suppose) to
automagically turn one of those pointers into a pointer to an
ErlDrvBinary.

-Scott

/* ------------- From erl_driver_tk.h */

/* Wrapper functions for driver_{alloc,realloc,free}_binary */
/*
** Use these as as you would use malloc(), realloc(), and free(), 
** respectively.
*/
void *edtk_driver_alloc_wrapper(size_t);
void *edtk_driver_realloc_wrapper(void *, size_t);
void edtk_driver_free_wrapper(void *);

/* Helper func */
ErlDrvBinary *edtk_alloced_ptr2ErlDrvBinary(void *);

/* ------------- From erl_driver_tk.c */

void *
edtk_driver_alloc_wrapper(size_t size)
{
    ErlDrvBinary        *eb;

    if ((eb = driver_alloc_binary(size)) != NULL) {
        return eb->orig_bytes;
    } else {
        return NULL;
    }
}

void *
edtk_driver_realloc_wrapper(void *p, size_t size)
{
    ErlDrvBinary        *eb, *neweb;

    if ((eb = edtk_alloced_ptr2ErlDrvBinary(p)) != NULL) {
        if ((neweb = driver_realloc_binary(eb, size)) != NULL) {
            return neweb->orig_bytes;
        } else {
            return NULL;
        }
    } else {
        return NULL;
    }
}

void
edtk_driver_free_wrapper(void *p)
{
    ErlDrvBinary        *eb;

    if ((eb = edtk_alloced_ptr2ErlDrvBinary(p)) != NULL) {
        driver_free_binary(eb);
    }
}

/* QQQ Make this a macro, use scratch static ErlDrvBinary? */
ErlDrvBinary *
edtk_alloced_ptr2ErlDrvBinary(void *p)
{
    ErlDrvBinary        stackeb;
    int                 offset = stackeb.orig_bytes - (char *) &stackeb;

    if (p != NULL) {
        return (ErlDrvBinary *) ((char *) p - offset);
    } else {
        return NULL;
    }
}

/* ------------- From example driver code... */

/*
** Callers almost always call with the beginning offset = 0.
*/

static int
reply_ok_binary(descriptor_t *desc, char *ptr, int beg_offset, int length)
{
    ErlDrvTermData      msg[15]; /* too big */
    int                 i = 0;
    int                 res;

    /*
    ** Up until now, the driver has been dealing with 'ptr'
    ** as if it had received it from malloc() or realloc().
    */
    i = LOAD_PORT(msg, i, driver_mk_port(desc->port));
    i = LOAD_ATOM(msg, i, am_ok);
    i = LOAD_BINARY(msg, i, edtk_alloced_ptr2ErlDrvBinary(ptr),
                    beg_offset, length);
    i = LOAD_TUPLE(msg, i, 3);
    res = driver_output_term(desc->port, msg, i);
    return res;
}




More information about the erlang-questions mailing list