diff --git a/examples/simple/example_decoder.c b/examples/simple/example_decoder.c
index 4eac10df2f2146a3fc7174a460e79a6906ca6d00..531d2efc4fa4bef056c365577670cfaba7770bab 100644
--- a/examples/simple/example_decoder.c
+++ b/examples/simple/example_decoder.c
@@ -56,7 +56,7 @@ int main(int argc, char *argv[]) {
   char *filename = argv[1];
   printf("C decoder reading from %s\n", filename);
   fd = open(filename, O_RDONLY);
-  decoder = labcomm_decoder_new(labcomm_fd_reader, &fd, NULL, NULL);
+  decoder = labcomm_decoder_new(labcomm_fd_reader_new(fd, 1), NULL, NULL);
   if (!decoder) { 
     printf("Failed to allocate decoder %s:%d\n", __FUNCTION__, __LINE__);
     return 1;
diff --git a/examples/simple/example_encoder.c b/examples/simple/example_encoder.c
index 5270c2bdbb7893d86d0be97c2d984a73af4f6f9a..eed3f3fdb4ca04b6f80723680ae1086c46d46fd2 100644
--- a/examples/simple/example_encoder.c
+++ b/examples/simple/example_encoder.c
@@ -12,7 +12,7 @@ int main(int argc, char *argv[]) {
   char *filename = argv[1];
   printf("C encoder writing to %s\n", filename);
   fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
-  encoder = labcomm_encoder_new(labcomm_fd_writer, &fd, NULL, NULL);
+  encoder = labcomm_encoder_new(labcomm_fd_writer_new(fd, 1), NULL, NULL);
   labcomm_encoder_register_simple_theTwoInts(encoder);
   labcomm_encoder_register_simple_anotherTwoInts(encoder);
   labcomm_encoder_register_simple_IntString(encoder);
diff --git a/lib/c/labcomm.c b/lib/c/labcomm.c
index 2a86b0e3a7a14097dbe800a420e2d81c4905fc7d..e02cf3f9b65d5cd7b583a4f80b55b0b257991f5c 100644
--- a/lib/c/labcomm.c
+++ b/lib/c/labcomm.c
@@ -38,7 +38,7 @@
 
 struct labcomm_decoder {
   void *context;
-  struct labcomm_reader reader;
+  struct labcomm_reader *reader;
   struct {
     void *context;
     const struct labcomm_lock_action *action;
@@ -49,7 +49,7 @@ struct labcomm_decoder {
 
 struct labcomm_encoder {
   void *context;
-  struct labcomm_writer writer;
+  struct labcomm_writer *writer;
   struct {
     void *context;
     const struct labcomm_lock_action *action;
@@ -88,13 +88,13 @@ struct labcomm_decoder_context {
 void labcomm_register_error_handler_encoder(struct labcomm_encoder *encoder, labcomm_error_handler_callback callback)
 {
  encoder->on_error = callback; 
- encoder->writer.on_error = callback; 
+ encoder->writer->on_error = callback; 
 }
 
 void labcomm_register_error_handler_decoder(struct labcomm_decoder *decoder, labcomm_error_handler_callback callback)
 {
  decoder->on_error = callback; 
- decoder->reader.on_error = callback; 
+ decoder->reader->on_error = callback; 
 }
 
 /* Error strings. _must_ be the same order as in enum labcomm_error */
@@ -251,19 +251,19 @@ static void labcomm_encode_signature(struct labcomm_encoder *e,
   int i, index;
 
   index = get_encoder_index(e, signature);
-  e->writer.action.start(&e->writer, e, index, signature, NULL);
-  labcomm_write_packed32(&e->writer, signature->type);
-  labcomm_write_packed32(&e->writer, index);
+  e->writer->action->start(e->writer, e, index, signature, NULL);
+  labcomm_write_packed32(e->writer, signature->type);
+  labcomm_write_packed32(e->writer, index);
 
-  labcomm_write_string(&e->writer, signature->name);
+  labcomm_write_string(e->writer, signature->name);
   for (i = 0 ; i < signature->size ; i++) {
-    if (e->writer.pos >= e->writer.count) {
-      e->writer.action.flush(&e->writer);
+    if (e->writer->pos >= e->writer->count) {
+      e->writer->action->flush(e->writer);
     }
-    e->writer.data[e->writer.pos] = signature->signature[i];
-    e->writer.pos++;
+    e->writer->data[e->writer->pos] = signature->signature[i];
+    e->writer->pos++;
   }
-  e->writer.action.end(&e->writer);
+  e->writer->action->end(e->writer);
 }
 
 #ifdef LABCOMM_ENCODER_LINEAR_SEARCH
@@ -356,8 +356,7 @@ static struct labcomm_sample_entry *encoder_get_sample_by_signature_address(
 */
 						    
 struct labcomm_encoder *labcomm_encoder_new(
-  const struct labcomm_writer_action writer,
-  void *writer_context,
+  struct labcomm_writer *writer,
   const struct labcomm_lock_action *lock,
   void *lock_context)
 {
@@ -373,18 +372,17 @@ struct labcomm_encoder *labcomm_encoder_new(
     context->by_section = NULL;
 #endif
     result->context = context;
-    result->writer.data = 0;
-    result->writer.data_size = 0;
-    result->writer.count = 0;
-    result->writer.pos = 0;
-    result->writer.error = 0;
-    result->writer.action = writer;
-    result->writer.context = writer_context;
+    result->writer = writer;
+    result->writer->data = 0;
+    result->writer->data_size = 0;
+    result->writer->count = 0;
+    result->writer->pos = 0;
+    result->writer->error = 0;
     result->lock.action = lock;
     result->lock.context = lock_context;
-    result->writer.on_error = on_error_fprintf;
+    result->writer->on_error = on_error_fprintf;
     result->on_error = on_error_fprintf;
-    result->writer.action.alloc(&result->writer, LABCOMM_VERSION);
+    result->writer->action->alloc(result->writer, LABCOMM_VERSION);
   }
   return result;
 }
@@ -424,21 +422,21 @@ int labcomm_internal_encode(
   int index;
 
   index = get_encoder_index(e, signature);
-  result = e->writer.action.start(&e->writer, e, index, signature, value);
+  result = e->writer->action->start(e->writer, e, index, signature, value);
   if (result == -EALREADY) { result = 0; goto no_end; }
   if (result != 0) { goto out; }
-  result = labcomm_write_packed32(&e->writer, index);
+  result = labcomm_write_packed32(e->writer, index);
   if (result != 0) { goto out; }
-  result = encode(&e->writer, value);
+  result = encode(e->writer, value);
 out:
-  e->writer.action.end(&e->writer);
+  e->writer->action->end(e->writer);
 no_end:
   return result;
 }
 
 void labcomm_encoder_free(struct labcomm_encoder* e)
 {
-  e->writer.action.free(&e->writer);
+  e->writer->action->free(e->writer);
   struct labcomm_encoder_context *context = (struct labcomm_encoder_context *) e->context;
 
 #ifdef LABCOMM_ENCODER_LINEAR_SEARCH
@@ -462,11 +460,11 @@ int labcomm_encoder_ioctl(struct labcomm_encoder *encoder,
 {
   int result = -ENOTSUP;
   
-  if (encoder->writer.action.ioctl != NULL) {
+  if (encoder->writer->action->ioctl != NULL) {
     va_list va;
     
     va_start(va, action);
-    result = encoder->writer.action.ioctl(&encoder->writer, action, NULL, va);
+    result = encoder->writer->action->ioctl(encoder->writer, action, NULL, va);
     va_end(va);
   }
   return result;
@@ -478,11 +476,11 @@ static int labcomm_writer_ioctl(struct labcomm_writer *writer,
 {
   int result = -ENOTSUP;
   
-  if (writer->action.ioctl != NULL) {
+  if (writer->action->ioctl != NULL) {
     va_list va;
     
     va_start(va, action);
-    result = writer->action.ioctl(writer, action, NULL, va);
+    result = writer->action->ioctl(writer, action, NULL, va);
     va_end(va);
   }
   return result;
@@ -495,9 +493,9 @@ int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
 {
   int result = -ENOTSUP;
   
-  if (encoder->writer.action.ioctl != NULL) {
-    result = encoder->writer.action.ioctl(&encoder->writer, action, 
-					  signature, va);
+  if (encoder->writer->action->ioctl != NULL) {
+    result = encoder->writer->action->ioctl(encoder->writer, action, 
+					    signature, va);
   }
   return result;
 }
@@ -506,7 +504,7 @@ static void collect_flat_signature(
   struct labcomm_decoder *decoder,
   struct labcomm_writer *writer)
 {
-  int type = labcomm_read_packed32(&decoder->reader); 
+  int type = labcomm_read_packed32(decoder->reader); 
   if (type >= LABCOMM_USER) {
     decoder->on_error(LABCOMM_ERROR_UNIMPLEMENTED_FUNC, 3,
 			"Implement %s ... (1) for type 0x%x\n", __FUNCTION__, type);
@@ -516,10 +514,10 @@ static void collect_flat_signature(
       case LABCOMM_ARRAY: {
 	int dimensions, i;
 
-	dimensions = labcomm_read_packed32(&decoder->reader);
+	dimensions = labcomm_read_packed32(decoder->reader);
 	labcomm_write_packed32(writer, dimensions);
 	for (i = 0 ; i < dimensions ; i++) {
-	  int n = labcomm_read_packed32(&decoder->reader);
+	  int n = labcomm_read_packed32(decoder->reader);
 	  labcomm_write_packed32(writer, n);
 	}
 	collect_flat_signature(decoder, writer);
@@ -527,10 +525,10 @@ static void collect_flat_signature(
       case LABCOMM_STRUCT: {
 	int fields, i;
 
-	fields = labcomm_read_packed32(&decoder->reader); 
+	fields = labcomm_read_packed32(decoder->reader); 
 	labcomm_write_packed32(writer, fields); 
 	for (i = 0 ; i < fields ; i++) {
-	  char *name = labcomm_read_string(&decoder->reader);
+	  char *name = labcomm_read_string(decoder->reader);
 	  labcomm_write_string(writer, name);
 	  free(name);
 	  collect_flat_signature(decoder, writer);
@@ -554,8 +552,7 @@ static void collect_flat_signature(
 }
 
 struct labcomm_decoder *labcomm_decoder_new(
-  const struct labcomm_reader_action reader,
-  void *reader_context,
+  struct labcomm_reader *reader,
   const struct labcomm_lock_action *lock,
   void *lock_context)
 {
@@ -565,18 +562,17 @@ struct labcomm_decoder *labcomm_decoder_new(
       (struct labcomm_decoder_context *)malloc(sizeof(*context));
     context->sample = 0;
     result->context = context;
-    result->reader.data = 0;
-    result->reader.data_size = 0;
-    result->reader.count = 0;
-    result->reader.pos = 0;
-    result->reader.action = reader;
-    result->reader.context = reader_context;
-    result->reader.on_error = on_error_fprintf;
+    result->reader = reader;
+    result->reader->data = 0;
+    result->reader->data_size = 0;
+    result->reader->count = 0;
+    result->reader->pos = 0;
+    result->reader->on_error = on_error_fprintf;
     result->lock.action = lock;
     result->lock.context = lock_context;
     result->on_error = on_error_fprintf;
     result->on_new_datatype = on_new_datatype;
-    result->reader.action.alloc(&result->reader, LABCOMM_VERSION);
+    result->reader->action->alloc(result->reader, LABCOMM_VERSION);
   }
   return result;
 }
@@ -608,87 +604,83 @@ int labcomm_decoder_decode_one(struct labcomm_decoder *d)
 {
   int result;
 
-  do {
-    result = d->reader.action.start(&d->reader);
-    if (result > 0) {
-      struct labcomm_decoder_context *context = d->context;
-
-      result = labcomm_read_packed32(&d->reader);
-      if (result == LABCOMM_TYPEDEF || result == LABCOMM_SAMPLE) {
-	/* TODO: should the labcomm_dynamic_buffer_writer be 
-	   a permanent part of labcomm_decoder? */
-	struct labcomm_writer writer = {
-	  .context = NULL,
-	  .data = NULL,
-	  .data_size = 0,
-	  .count = 0,
-	  .pos = 0,
-	  .error = 0,
-	  .action = labcomm_dynamic_buffer_writer,
-	  .on_error = NULL
-	};
-	struct labcomm_signature signature;
-	struct labcomm_sample_entry *entry = NULL;
-	int index, err;
-
-	writer.action.alloc(&writer, "");
-	writer.action.start(&writer, NULL, 0, NULL, NULL);
-	index = labcomm_read_packed32(&d->reader); //int
-	signature.name = labcomm_read_string(&d->reader);
-	signature.type = result;
-	collect_flat_signature(d, &writer);
-	writer.action.end(&writer);
-	err = labcomm_writer_ioctl(&writer, 
-				   LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
-				   &signature.size);
-	if (err < 0) {
-	  printf("Failed to get size: %s\n", strerror(-err));
-	  goto free_signature_name;
-	}
-	err = labcomm_writer_ioctl(&writer, 
-				   LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER,
-				   &signature.signature);
-	if (err < 0) {
-	  printf("Failed to get pointer: %s\n", strerror(-err));
-	  goto free_signature_name;
-	}
-	entry = get_sample_by_signature_value(context->sample, &signature);
-	if (! entry) {
-	  /* Unknown datatype, bail out */
-	  d->on_new_datatype(d, &signature);
-	} else if (entry->index && entry->index != index) {
-          d->on_error(LABCOMM_ERROR_DEC_INDEX_MISMATCH, 5, 
-		      "%s(): index mismatch '%s' (id=0x%x != 0x%x)\n", 
-		      __FUNCTION__, signature.name, entry->index, index);
-	} else {
-	  // TODO unnessesary, since entry->index == index in above if statement
-	  entry->index = index;
-	}
-      free_signature_name:
-	free(signature.name);
-	writer.action.free(&writer);
-	if (!entry) {
-	  // No handler for found type, bail out (after cleanup)
-	  result = -ENOENT;
-	}
+  result = d->reader->action->start(d->reader);
+  if (result > 0) {
+    struct labcomm_decoder_context *context = d->context;
+    
+    result = labcomm_read_packed32(d->reader);
+    if (result == LABCOMM_TYPEDEF || result == LABCOMM_SAMPLE) {
+      /* TODO: should the labcomm_dynamic_buffer_writer be 
+	 a permanent part of labcomm_decoder? */
+      struct labcomm_writer writer = {
+	.context = NULL,
+	.data = NULL,
+	.data_size = 0,
+	.count = 0,
+	.pos = 0,
+	.error = 0,
+	.action = labcomm_dynamic_buffer_writer_action,
+	.on_error = NULL
+      };
+      struct labcomm_signature signature;
+      struct labcomm_sample_entry *entry = NULL;
+      int index, err;
+      
+      writer.action->alloc(&writer, "");
+      writer.action->start(&writer, NULL, 0, NULL, NULL);
+      index = labcomm_read_packed32(d->reader); //int
+      signature.name = labcomm_read_string(d->reader);
+      signature.type = result;
+      collect_flat_signature(d, &writer);
+      writer.action->end(&writer);
+      err = labcomm_writer_ioctl(&writer, 
+				 LABCOMM_IOCTL_WRITER_GET_BYTES_WRITTEN,
+				 &signature.size);
+      if (err < 0) {
+	printf("Failed to get size: %s\n", strerror(-err));
+	goto free_signature_name;
+      }
+      err = labcomm_writer_ioctl(&writer, 
+				 LABCOMM_IOCTL_WRITER_GET_BYTE_POINTER,
+				 &signature.signature);
+      if (err < 0) {
+	printf("Failed to get pointer: %s\n", strerror(-err));
+	goto free_signature_name;
+      }
+      entry = get_sample_by_signature_value(context->sample, &signature);
+      if (! entry) {
+	/* Unknown datatype, bail out */
+	d->on_new_datatype(d, &signature);
+      } else if (entry->index && entry->index != index) {
+	d->on_error(LABCOMM_ERROR_DEC_INDEX_MISMATCH, 5, 
+		    "%s(): index mismatch '%s' (id=0x%x != 0x%x)\n", 
+		    __FUNCTION__, signature.name, entry->index, index);
       } else {
-	struct labcomm_sample_entry *entry;
-
-	entry = get_sample_by_index(context->sample, result);
-	if (!entry) {
-	  // printf("Error: %s: type not found (id=0x%x)\n",
-		  //__FUNCTION__, result);
-          d->on_error(LABCOMM_ERROR_DEC_TYPE_NOT_FOUND, 3, "%s(): type not found (id=0x%x)\n", __FUNCTION__, result);
-	  result = -ENOENT;
-	} else {
-	  entry->decoder(&d->reader, entry->handler, entry->context);
-	}
+	// TODO unnessesary, since entry->index == index in above if statement
+	entry->index = index;
+      }
+    free_signature_name:
+      free(signature.name);
+      writer.action->free(&writer);
+      if (!entry) {
+	// No handler for found type, bail out (after cleanup)
+	result = -ENOENT;
+      }
+    } else {
+      struct labcomm_sample_entry *entry;
+      
+      entry = get_sample_by_index(context->sample, result);
+      if (!entry) {
+	// printf("Error: %s: type not found (id=0x%x)\n",
+	//__FUNCTION__, result);
+	d->on_error(LABCOMM_ERROR_DEC_TYPE_NOT_FOUND, 3, "%s(): type not found (id=0x%x)\n", __FUNCTION__, result);
+	result = -ENOENT;
+      } else {
+	entry->decoder(d->reader, entry->handler, entry->context);
       }
     }
-    d->reader.action.end(&d->reader);
-    /* TODO: should we really loop, or is it OK to
-       return after a typedef/sample */
-  } while (result > 0 && result < LABCOMM_USER);
+  }
+  d->reader->action->end(d->reader);
   return result;
 }
 
@@ -700,7 +692,7 @@ void labcomm_decoder_run(struct labcomm_decoder *d)
 
 void labcomm_decoder_free(struct labcomm_decoder* d)
 {
-  d->reader.action.free(&d->reader);
+  d->reader->action->free(d->reader);
   struct labcomm_decoder_context *context = (struct labcomm_decoder_context *) d->context;
   struct labcomm_sample_entry *entry = context->sample;
   struct labcomm_sample_entry *entry_next;
@@ -721,11 +713,11 @@ int labcomm_decoder_ioctl(struct labcomm_decoder *decoder,
 {
   int result = -ENOTSUP;
   
-  if (decoder->reader.action.ioctl != NULL) {
+  if (decoder->reader->action->ioctl != NULL) {
     va_list va;
     
     va_start(va, action);
-    result = decoder->reader.action.ioctl(&decoder->reader, action, NULL, va);
+    result = decoder->reader->action->ioctl(decoder->reader, action, NULL, va);
     va_end(va);
   }
   return result;
@@ -738,8 +730,8 @@ int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder,
 {
   int result = -ENOTSUP;
   
-  if (decoder->reader.action.ioctl != NULL) {
-    result = decoder->reader.action.ioctl(&decoder->reader, action, NULL, va);
+  if (decoder->reader->action->ioctl != NULL) {
+    result = decoder->reader->action->ioctl(decoder->reader, action, NULL, va);
   }
   return result;
 }
diff --git a/lib/c/labcomm.h b/lib/c/labcomm.h
index 97eaa4a813136ae9c7bde788519b4957df333c0d..e306493fe1b6938fdcd4fcfb3608ef65ce9aef28 100644
--- a/lib/c/labcomm.h
+++ b/lib/c/labcomm.h
@@ -92,32 +92,10 @@ struct labcomm_lock_action {
 /*
  * Decoder
  */
-
 struct labcomm_reader;
 
-struct labcomm_reader_action {
-  int (*alloc)(struct labcomm_reader *r, char *labcomm_version);
-  int (*free)(struct labcomm_reader *r);
-  int (*start)(struct labcomm_reader *r);
-  int (*end)(struct labcomm_reader *r);
-  int (*fill)(struct labcomm_reader *r); 
-  int (*ioctl)(struct labcomm_reader *r, int, struct labcomm_signature *, va_list);
-};
-
-struct labcomm_reader {
-  void *context;
-  unsigned char *data;
-  int data_size;
-  int count;
-  int pos;
-  int error;
-  struct labcomm_reader_action action;
-  labcomm_error_handler_callback on_error;
-};
-
 struct labcomm_decoder *labcomm_decoder_new(
-  const struct labcomm_reader_action reader,
-  void *reader_context,
+  struct labcomm_reader *reader,
   const struct labcomm_lock_action *lock,
   void *lock_context);
 int labcomm_decoder_decode_one(
@@ -137,34 +115,8 @@ int labcomm_decoder_ioctl(struct labcomm_decoder *decoder,
  */
 struct labcomm_writer;
 
-struct labcomm_writer_action {
-  int (*alloc)(struct labcomm_writer *w, char *labcomm_version);
-  int (*free)(struct labcomm_writer *w);
-  int (*start)(struct labcomm_writer *w,
-	       struct labcomm_encoder *encoder,
-	       int index, struct labcomm_signature *signature,
-	       void *value);
-  int (*end)(struct labcomm_writer *w);
-  int (*flush)(struct labcomm_writer *w); 
-  int (*ioctl)(struct labcomm_writer *w, 
-	       int index, struct labcomm_signature *, 
-	       va_list);
-};
-
-struct labcomm_writer {
-  void *context;
-  unsigned char *data;
-  int data_size;
-  int count;
-  int pos;
-  int error;
-  struct labcomm_writer_action action;
-  labcomm_error_handler_callback on_error;
-};
-
 struct labcomm_encoder *labcomm_encoder_new(
-  const struct labcomm_writer_action writer,
-  void *writer_context,
+  struct labcomm_writer *writer,
   const struct labcomm_lock_action *lock,
   void *lock_context);
 void labcomm_encoder_free(
diff --git a/lib/c/labcomm_dynamic_buffer_writer.c b/lib/c/labcomm_dynamic_buffer_writer.c
index b58a711b726afcf08e096bb693881f88b178dfac..8c83dee956e710eaed59660c0c181949522c804a 100644
--- a/lib/c/labcomm_dynamic_buffer_writer.c
+++ b/lib/c/labcomm_dynamic_buffer_writer.c
@@ -1,6 +1,8 @@
 #include <errno.h>
 #include <stdlib.h>
 #include <stdarg.h>
+#include "labcomm.h"
+#include "labcomm_private.h"
 #include "labcomm_ioctl.h"
 #include "labcomm_dynamic_buffer_writer.h"
 
@@ -93,7 +95,7 @@ static int dyn_ioctl(struct labcomm_writer *w,
   return result;
 }
 
-const struct labcomm_writer_action labcomm_dynamic_buffer_writer = {
+static const struct labcomm_writer_action action = {
   .alloc = dyn_alloc,
   .free = dyn_free,
   .start = dyn_start,
@@ -101,3 +103,18 @@ const struct labcomm_writer_action labcomm_dynamic_buffer_writer = {
   .flush = dyn_flush,
   .ioctl = dyn_ioctl
 };
+const struct labcomm_writer_action *labcomm_dynamic_buffer_writer_action = 
+  &action;
+
+struct labcomm_writer *labcomm_dynamic_buffer_writer_new()
+{
+  struct labcomm_writer *result;
+
+  result = malloc(sizeof(*result));
+  if (result != NULL) {
+    result->context = NULL;
+    result->action = &action;
+  }
+  return result;
+}
+
diff --git a/lib/c/labcomm_dynamic_buffer_writer.h b/lib/c/labcomm_dynamic_buffer_writer.h
index 63099ef1b41b7d25dea3df5b85fc9ec28ff0fa25..7f01a1dfd0eda72722d0cff97902617f523d70f6 100644
--- a/lib/c/labcomm_dynamic_buffer_writer.h
+++ b/lib/c/labcomm_dynamic_buffer_writer.h
@@ -3,6 +3,6 @@
 
 #include "labcomm.h"
 
-extern const struct labcomm_writer_action labcomm_dynamic_buffer_writer;
+extern const struct labcomm_writer_action *labcomm_dynamic_buffer_writer_action;
 
 #endif
diff --git a/lib/c/labcomm_fd_reader.c b/lib/c/labcomm_fd_reader.c
index f49be47ac957ba549c5445b7f8f2cf9cee200841..f8b6f50f1cf86dd8c31fb22f6ee9c68e5ae5f1c2 100644
--- a/lib/c/labcomm_fd_reader.c
+++ b/lib/c/labcomm_fd_reader.c
@@ -7,6 +7,12 @@
 
 #define BUFFER_SIZE 2048
 
+struct labcomm_fd_reader {
+  struct labcomm_reader reader;
+  int fd;
+  int close_fd_on_free;
+};
+
 static int fd_alloc(struct labcomm_reader *r, char *version)
 {
   int result = 0;
@@ -18,35 +24,46 @@ static int fd_alloc(struct labcomm_reader *r, char *version)
     r->data_size = 0;
     result = -ENOMEM;
   } else {
-    char *tmp;
 
     r->data_size = BUFFER_SIZE;
-    tmp = labcomm_read_string(r);
-    if (strcmp(tmp, version) != 0) {
-      result = -EINVAL;
-    } else {
-      result = r->data_size;
+    result = r->data_size;
+    if (version && version[0]) {
+      char *tmp;
+      
+      tmp = labcomm_read_string(r);
+      if (strcmp(tmp, version) != 0) {
+	result = -EINVAL;
+      } else {
+	result = r->data_size;
+      }
+      free(tmp);
     }
-    free(tmp);
   }
   return result;
 }
 
 static int fd_free(struct labcomm_reader *r)
 {
+  struct labcomm_fd_reader *context = r->context;
+
   free(r->data);
   r->data = 0;
   r->data_size = 0;
   r->count = 0;
   r->pos = 0;
 
+  if (context->close_fd_on_free) {
+    close(context->fd);
+  }
+  free(context);
+
   return 0;
 }
 
 static int fd_fill(struct labcomm_reader *r)
 {
   int result = 0;
-  int *fd = r->context;
+  struct labcomm_fd_reader *context = r->context;
 
   if (r->pos < r->count) {
     result = r->count - r->pos;
@@ -54,7 +71,7 @@ static int fd_fill(struct labcomm_reader *r)
     int err;
     
     r->pos = 0;
-    err = read(*fd, r->data, r->data_size);
+    err = read(context->fd, r->data, r->data_size);
     if (err <= 0) {
       r->count = 0;
       result = -EPIPE;
@@ -76,7 +93,7 @@ static int fd_end(struct labcomm_reader *r)
   return 0;
 }
 
-const struct labcomm_reader_action labcomm_fd_reader = {
+static const struct labcomm_reader_action action = {
   .alloc = fd_alloc,
   .free = fd_free,
   .start = fd_start,
@@ -84,3 +101,19 @@ const struct labcomm_reader_action labcomm_fd_reader = {
   .end = fd_end,
   .ioctl = NULL
 };
+
+struct labcomm_reader *labcomm_fd_reader_new(int fd, int close_fd_on_free)
+{
+  struct labcomm_fd_reader *result;
+
+  result = malloc(sizeof(*result));
+  if (result == NULL) {
+    return NULL;
+  } else {
+    result->fd = fd;
+    result->close_fd_on_free = close_fd_on_free;
+    result->reader.context = result;
+    result->reader.action = &action;
+    return &result->reader;
+  }
+}
diff --git a/lib/c/labcomm_fd_reader.h b/lib/c/labcomm_fd_reader.h
index 55882cf0e049fe6908677eecade680e5345d7c2a..8f526fa3d9f828b77f4838f1fdee12bd62160a6f 100644
--- a/lib/c/labcomm_fd_reader.h
+++ b/lib/c/labcomm_fd_reader.h
@@ -3,7 +3,7 @@
 
 #include "labcomm.h"
 
-extern const struct labcomm_reader_action labcomm_fd_reader;
+struct labcomm_reader *labcomm_fd_reader_new(int fd, int close_fd_on_free);
 
 #endif
 
diff --git a/lib/c/labcomm_fd_writer.c b/lib/c/labcomm_fd_writer.c
index ce3d8bdf5bf7ebab8ab03fe06003cd5e95632197..88a77805c7d7bbbdb85e1fb84aa0f5e1bdb5079a 100644
--- a/lib/c/labcomm_fd_writer.c
+++ b/lib/c/labcomm_fd_writer.c
@@ -8,6 +8,12 @@
 
 #define BUFFER_SIZE 2048
 
+struct labcomm_fd_writer {
+  struct labcomm_writer writer;
+  int fd;
+  int close_fd_on_free;
+};
+
 static int fd_flush(struct labcomm_writer *w);
 
 static int fd_alloc(struct labcomm_writer *w, char *version)
@@ -22,8 +28,10 @@ static int fd_alloc(struct labcomm_writer *w, char *version)
     w->data_size = BUFFER_SIZE;
     w->count = BUFFER_SIZE;
     w->pos = 0;
-    labcomm_write_string(w, version);
-    fd_flush(w);
+    if (version && version[0]) {
+      labcomm_write_string(w, version);
+      fd_flush(w);
+    }
   }
 
   return w->error;
@@ -31,12 +39,17 @@ static int fd_alloc(struct labcomm_writer *w, char *version)
 
 static int fd_free(struct labcomm_writer *w)
 {
+  struct labcomm_fd_writer *context = w->context;
+
   free(w->data);
   w->data = 0;
   w->data_size = 0;
   w->count = 0;
   w->pos = 0;
 
+  if (context->close_fd_on_free) {
+    close(context->fd);
+  }
   return 0;
 }
 
@@ -53,10 +66,10 @@ static int fd_start(struct labcomm_writer *w,
 
 static int fd_flush(struct labcomm_writer *w)
 {
-  int *fd = w->context;
+  struct labcomm_fd_writer *context = w->context;
   int err;
 
-  err = write(*fd, w->data, w->pos);
+  err = write(context->fd, w->data, w->pos);
   if (err < 0) {
     w->error = -errno;
   } else if (err == 0) {
@@ -67,7 +80,7 @@ static int fd_flush(struct labcomm_writer *w)
   return w->error;
 }
 
-const struct labcomm_writer_action labcomm_fd_writer = {
+static const struct labcomm_writer_action action = {
   .alloc = fd_alloc,
   .free = fd_free,
   .start = fd_start,
@@ -75,3 +88,19 @@ const struct labcomm_writer_action labcomm_fd_writer = {
   .flush = fd_flush,
   .ioctl = NULL
 };
+
+struct labcomm_writer *labcomm_fd_writer_new(int fd, int close_fd_on_free)
+{
+  struct labcomm_fd_writer *result;
+
+  result = malloc(sizeof(*result));
+  if (result == NULL) {
+    return NULL;
+  } else {
+    result->fd = fd;
+    result->close_fd_on_free = close_fd_on_free;
+    result->writer.context = result;
+    result->writer.action = &action;
+    return &result->writer;
+  }
+}
diff --git a/lib/c/labcomm_fd_writer.h b/lib/c/labcomm_fd_writer.h
index 39d0258955366330a42077223f5595b44539e5d0..e1c976a390c96ea3afc534b5f8a3543de3a1cd3c 100644
--- a/lib/c/labcomm_fd_writer.h
+++ b/lib/c/labcomm_fd_writer.h
@@ -3,7 +3,7 @@
 
 #include "labcomm.h"
 
-extern const struct labcomm_writer_action labcomm_fd_writer;
+struct labcomm_writer *labcomm_fd_writer_new(int fd, int close_on_free);
 
 #endif
 
diff --git a/lib/c/labcomm_private.h b/lib/c/labcomm_private.h
index 49363f0c084439a8a864b3bc2e662d6e00064e79..0f08ffbed338cdee5afe9bac5bd288b583fa4b33 100644
--- a/lib/c/labcomm_private.h
+++ b/lib/c/labcomm_private.h
@@ -54,6 +54,28 @@ typedef void (*labcomm_decoder_function)(
   labcomm_handler_function handler,
   void *context);
 
+struct labcomm_reader_action {
+  int (*alloc)(struct labcomm_reader *r, char *labcomm_version);
+  int (*free)(struct labcomm_reader *r);
+  int (*start)(struct labcomm_reader *r);
+  int (*end)(struct labcomm_reader *r);
+  int (*fill)(struct labcomm_reader *r); 
+  int (*ioctl)(struct labcomm_reader *r, int, struct labcomm_signature *, va_list);
+};
+
+struct labcomm_reader {
+  const struct labcomm_reader_action *action;
+  void *context;
+  unsigned char *data;
+  int data_size;
+  int count;
+  int pos;
+  int error;
+  labcomm_error_handler_callback on_error;
+};
+
+
+
 /*
  * Non typesafe registration function to be called from
  * generated labcomm_decoder_register_* functions.
@@ -77,7 +99,7 @@ int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder,
     type result; int i;							\
     for (i = sizeof(type) - 1 ; i >= 0 ; i--) {				\
       if (r->pos >= r->count) {						\
-	r->action.fill(r);						\
+	r->action->fill(r);						\
       }									\
       ((unsigned char*)(&result))[i] = r->data[r->pos];			\
       r->pos++;								\
@@ -92,7 +114,7 @@ int labcomm_internal_decoder_ioctl(struct labcomm_decoder *decoder,
     type result; int i;							\
     for (i = 0 ; i < sizeof(type) ; i++) {				\
       if (r->pos >= r->count) {						\
-	r->action.fill(r);						\
+	r->action->fill(r);						\
       }									\
       ((unsigned char*)(&result))[i] = r->data[r->pos];			\
       r->pos++;								\
@@ -118,7 +140,7 @@ static inline unsigned int labcomm_read_packed32(struct labcomm_reader *r)
     unsigned char tmp;
 
     if (r->pos >= r->count) {	
-      r->action.fill(r);
+      r->action->fill(r);
     }
     tmp = r->data[r->pos];
     r->pos++;
@@ -139,7 +161,7 @@ static inline char *labcomm_read_string(struct labcomm_reader *r)
   result = malloc(length + 1);
   for (i = 0 ; i < length ; i++) {
     if (r->pos >= r->count) {	
-      r->action.fill(r);
+      r->action->fill(r);
     }
     result[i] = r->data[r->pos];
     r->pos++;
@@ -155,6 +177,33 @@ typedef int (*labcomm_encoder_function)(
   struct labcomm_writer *,
   void *value);
 
+struct labcomm_writer;
+
+struct labcomm_writer_action {
+  int (*alloc)(struct labcomm_writer *w, char *labcomm_version);
+  int (*free)(struct labcomm_writer *w);
+  int (*start)(struct labcomm_writer *w,
+	       struct labcomm_encoder *encoder,
+	       int index, struct labcomm_signature *signature,
+	       void *value);
+  int (*end)(struct labcomm_writer *w);
+  int (*flush)(struct labcomm_writer *w); 
+  int (*ioctl)(struct labcomm_writer *w, 
+	       int index, struct labcomm_signature *, 
+	       va_list);
+};
+
+struct labcomm_writer {
+  const struct labcomm_writer_action *action;
+  void *context;
+  unsigned char *data;
+  int data_size;
+  int count;
+  int pos;
+  int error;
+  labcomm_error_handler_callback on_error;
+};
+
 void labcomm_internal_encoder_register(
   struct labcomm_encoder *encoder, 
   struct labcomm_signature *signature, 
@@ -166,6 +215,7 @@ int labcomm_internal_encode(
   labcomm_encoder_function encode,
   void *value);
 
+
 int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder, 
 				   int ioctl_action,
 				   struct labcomm_signature *signature,
@@ -179,7 +229,7 @@ int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
     for (i = sizeof(type) - 1 ; i >= 0 ; i--) {				\
       if (w->pos >= w->count) { /*buffer is full*/			\
         int err;							\
-	err = w->action.flush(w);					\
+	err = w->action->flush(w);					\
 	if (err != 0) { return err; }					\
       }									\
       w->data[w->pos] = ((unsigned char*)(&data))[i];			\
@@ -196,7 +246,7 @@ int labcomm_internal_encoder_ioctl(struct labcomm_encoder *encoder,
     for (i = 0 ; i < sizeof(type) ; i++) {				\
       if (w->pos >= w->count) {						\
         int err;							\
-	err = w->action.flush(w);					\
+	err = w->action->flush(w);					\
 	if (err != 0) { return err; }					\
       }									\
       w->data[w->pos] = ((unsigned char*)(&data))[i];			\
@@ -227,7 +277,7 @@ static inline int labcomm_write_packed32(struct labcomm_writer *w,
   for (i = i - 1 ; i >= 0 ; i--) {
     if (w->pos >= w->count) {					
       int err;
-      err = w->action.flush(w);
+      err = w->action->flush(w);
       if (err != 0) { return err; }
     }
     w->data[w->pos++] = tmp[i] | (i?0x80:0x00);
@@ -245,7 +295,7 @@ static inline int labcomm_write_string(struct labcomm_writer *w, char *s)
   for (i = 0 ; i < length ; i++) {
     if (w->pos >= w->count) {	
       int err;
-      err = w->action.flush(w);
+      err = w->action->flush(w);
       if (err != 0) { return err; }
     }
     w->data[w->pos] = s[i];
diff --git a/lib/c/test/test_labcomm_basic_type_encoding.c b/lib/c/test/test_labcomm_basic_type_encoding.c
index ae57f1cd13263670cc2cbd0ca7e63ab429891c0c..9ca863eafcff28456ef944084035ac0b4e0eac08 100644
--- a/lib/c/test/test_labcomm_basic_type_encoding.c
+++ b/lib/c/test/test_labcomm_basic_type_encoding.c
@@ -14,7 +14,7 @@ static struct labcomm_writer writer =  {
   .count = sizeof(buffer),
   .pos = 0,
   .error = 0,
-  .action = { NULL, NULL, NULL, NULL, NULL, NULL },
+  .action = NULL,
   .on_error = NULL,
 };
 
@@ -24,7 +24,7 @@ static struct labcomm_reader reader =  {
   .data_size = sizeof(buffer),
   .count = 0,
   .pos = 0,
-  .action = { NULL, NULL, NULL, NULL, NULL, NULL },
+  .action = NULL,
   .on_error = NULL,
 };
 
diff --git a/lib/c/test/test_labcomm_generated_encoding.c b/lib/c/test/test_labcomm_generated_encoding.c
index 5b8cb66292adadee4f0b7f706257165cd51bf59c..1b0dd7fa522242f9be3558a335c4ce6ce9c1eb5f 100644
--- a/lib/c/test/test_labcomm_generated_encoding.c
+++ b/lib/c/test/test_labcomm_generated_encoding.c
@@ -101,7 +101,7 @@ static int buf_writer_ioctl(
   return result;
 }
 
-const struct labcomm_writer_action buffer_writer = {
+const struct labcomm_writer_action writer_action = {
   .alloc = buf_writer_alloc,
   .free = buf_writer_free,
   .start = buf_writer_start,
@@ -110,6 +110,17 @@ const struct labcomm_writer_action buffer_writer = {
   .ioctl = buf_writer_ioctl
 };
 
+static struct labcomm_writer buffer_writer = {
+  .context = NULL,
+  .data = buffer,
+  .data_size = sizeof(buffer),
+  .count = sizeof(buffer),
+  .pos = 0,
+  .error = 0,
+  .action = &writer_action,
+  .on_error = NULL,
+};
+
 void dump_encoder(struct labcomm_encoder *encoder)
 {
   int i;
@@ -134,8 +145,8 @@ int main(void)
   generated_encoding_V V;
   generated_encoding_B B = 1;
 
-  struct labcomm_encoder *encoder = labcomm_encoder_new(buffer_writer, buffer,
-						   NULL, NULL);
+  struct labcomm_encoder *encoder = labcomm_encoder_new(&buffer_writer, 
+							NULL, NULL);
 
   labcomm_encoder_ioctl(encoder, IOCTL_WRITER_RESET);
   labcomm_encoder_register_generated_encoding_V(encoder);
diff --git a/test/relay_gen_c.py b/test/relay_gen_c.py
index 72978045dda49ac6d29f27cd68b844576bae6c72..75aaa46a476b2a3a4efb89e02f5092298bf87fbe 100755
--- a/test/relay_gen_c.py
+++ b/test/relay_gen_c.py
@@ -50,8 +50,8 @@ if __name__ == '__main__':
       |  if (in < 0) { return 1; }
       |  out = open(argv[2], O_WRONLY);
       |  if (out < 0) { return 1; }
-      |  e = labcomm_encoder_new(labcomm_fd_writer, &out, NULL, NULL);
-      |  d = labcomm_decoder_new(labcomm_fd_reader, &in, NULL, NULL);
+      |  e = labcomm_encoder_new(labcomm_fd_writer_new(out, 1), NULL, NULL);
+      |  d = labcomm_decoder_new(labcomm_fd_reader_new(in, 1), NULL, NULL);
     """))
     for func,arg in sample:
         result.extend(split_match('^[^|]*\|(.*)$', """