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