diff --git a/adaptors/julia/AnalogIn.jl b/adaptors/julia/AnalogIn.jl
index 1a2736ef79001aac42d8fcd48c8aa7f8cc00df57..d3a577f2154edb05f3e05662452b7e2403c03b31 100644
--- a/adaptors/julia/AnalogIn.jl
+++ b/adaptors/julia/AnalogIn.jl
@@ -4,16 +4,17 @@ mutable struct AnalogInChannel
 end
 
 mutable struct AnalogIn
-    moberg::Moberg
+    moberg::Ptr{Nothing}
     index::UInt32
     channel::AnalogInChannel
     function AnalogIn(moberg::Moberg, index::Unsigned)
         channel = AnalogInChannel(0,0)
+        moberg_handle = moberg.handle
         checkOK(ccall((:moberg_analog_in_open, "libmoberg"),
                        Status,
-                       (Moberg, Cint, Ref{AnalogInChannel}),
-                       moberg, index, channel))
-        self = new(moberg, index, channel)
+                       (Ptr{Nothing}, Cint, Ref{AnalogInChannel}),
+                       moberg_handle, index, channel))
+        self = new(moberg_handle, index, channel)
         finalizer(close, self)
         self
     end
@@ -23,7 +24,7 @@ function close(ain::AnalogIn)
     DEBUG && println("closing $(ain)")
     checkOK(ccall((:moberg_analog_in_close, "libmoberg"),
                   Status,
-                  (Moberg, Cint, AnalogInChannel),
+                  (Ptr{Nothing}, Cint, AnalogInChannel),
                   ain.moberg, ain.index, ain.channel))
 end
 
diff --git a/adaptors/julia/AnalogOut.jl b/adaptors/julia/AnalogOut.jl
index 938a562a9a453bb9be86b7713b056c9407c6a032..a911d103c57c7521c8476953e64e08414052cc39 100644
--- a/adaptors/julia/AnalogOut.jl
+++ b/adaptors/julia/AnalogOut.jl
@@ -4,16 +4,17 @@ mutable struct AnalogOutChannel
 end
 
 mutable struct AnalogOut
-    moberg::Moberg
+    moberg::Ptr{Nothing}
     index::UInt32
     channel::AnalogOutChannel
     function AnalogOut(moberg::Moberg, index::Unsigned)
         channel = AnalogOutChannel(0,0)
+        moberg_handle = moberg.handle
         checkOK(ccall((:moberg_analog_out_open, "libmoberg"),
                        Status,
-                       (Moberg, Cint, Ref{AnalogOutChannel}),
-                       moberg, index, channel));
-        self = new(moberg, index, channel)
+                       (Ptr{Nothing}, Cint, Ref{AnalogOutChannel}),
+                       moberg_handle, index, channel));
+        self = new(moberg_handle, index, channel)
         finalizer(close, self)
         self
     end
@@ -23,7 +24,7 @@ function close(aout::AnalogOut)
     DEBUG && println("closing $(aout)")
     checkOK(ccall((:moberg_analog_out_close, "libmoberg"),
                   Status,
-                  (Moberg, Cint, AnalogOutChannel),
+                  (Ptr{Nothing}, Cint, AnalogOutChannel),
                   aout.moberg, aout.index, aout.channel))
 end
 
diff --git a/adaptors/julia/DigitalIn.jl b/adaptors/julia/DigitalIn.jl
index db662308cc317d1089f94364cddf6ee863f5e0f6..ba3f150db28cc1ffcc7d77782a64821f607f15e7 100644
--- a/adaptors/julia/DigitalIn.jl
+++ b/adaptors/julia/DigitalIn.jl
@@ -4,16 +4,17 @@ mutable struct DigitalInChannel
 end
 
 mutable struct DigitalIn
-    moberg::Moberg
+    moberg::Ptr{Nothing}
     index::UInt32
     channel::DigitalInChannel
     function DigitalIn(moberg::Moberg, index::Unsigned)
         channel = DigitalInChannel(0,0)
+        moberg_handle = moberg.handle
         checkOK(ccall((:moberg_digital_in_open, "libmoberg"),
                        Status,
-                       (Moberg, Cint, Ref{DigitalInChannel}),
-                       moberg, index, channel));
-        self = new(moberg, index, channel)
+                       (Ptr{Nothing}, Cint, Ref{DigitalInChannel}),
+                       moberg_handle, index, channel));
+        self = new(moberg_handle, index, channel)
         finalizer(close, self)
         self
     end
@@ -23,7 +24,7 @@ function close(din::DigitalIn)
     DEBUG && println("closing $(din)")
     checkOK(ccall((:moberg_digital_in_close, "libmoberg"),
                   Status,
-                  (Moberg, Cint, DigitalInChannel),
+                  (Ptr{Nothing}, Cint, DigitalInChannel),
                   din.moberg, din.index, din.channel))
 end
 
diff --git a/adaptors/julia/DigitalOut.jl b/adaptors/julia/DigitalOut.jl
index b76ffb796787763f94c4c7fada5fba8be4ddfaf6..3c978fbbcb4d9650daf35e503370618ff7cce76a 100644
--- a/adaptors/julia/DigitalOut.jl
+++ b/adaptors/julia/DigitalOut.jl
@@ -4,16 +4,17 @@ mutable struct DigitalOutChannel
 end
 
 mutable struct DigitalOut
-    moberg::Moberg
+    moberg::Ptr{Nothing}
     index::UInt32
     channel::DigitalOutChannel
     function DigitalOut(moberg::Moberg, index::Unsigned)
         channel = DigitalOutChannel(0,0)
+        moberg_handle = moberg.handle
         checkOK(ccall((:moberg_digital_out_open, "libmoberg"),
                        Status,
-                       (Moberg, Cint, Ref{DigitalOutChannel}),
-                       moberg, index, channel))
-        self = new(moberg, index, channel)
+                       (Ptr{Nothing}, Cint, Ref{DigitalOutChannel}),
+                       moberg_handle, index, channel))
+        self = new(moberg_handle, index, channel)
         finalizer(close, self)
         self
     end
@@ -23,7 +24,7 @@ function close(dout::DigitalOut)
     DEBUG && println("closing $(dout)")
     checkOK(ccall((:moberg_digital_out_close, "libmoberg"),
                   Status,
-                  (Moberg, Cint, DigitalOutChannel),
+                  (Ptr{Nothing}, Cint, DigitalOutChannel),
                   dout.moberg, dout.index, dout.channel))
 end
 
diff --git a/adaptors/julia/EncoderIn.jl b/adaptors/julia/EncoderIn.jl
index 2b05def7860ee0f821d65ed40d6272a496a48fea..58273f65a98d646805cc5bb266149d5f1f90a697 100644
--- a/adaptors/julia/EncoderIn.jl
+++ b/adaptors/julia/EncoderIn.jl
@@ -4,16 +4,17 @@ mutable struct EncoderInChannel
 end
 
 mutable struct EncoderIn
-    moberg::Moberg
+    moberg::Ptr{Nothing}
     index::UInt32
     channel::EncoderInChannel
     function EncoderIn(moberg::Moberg, index::Unsigned)
         channel = EncoderInChannel(0,0)
+        moberg_handle = moberg.handle
         checkOK(ccall((:moberg_encoder_in_open, "libmoberg"),
                        Status,
-                       (Moberg, Cint, Ref{EncoderInChannel}),
-                       moberg, index, channel))
-        self = new(moberg, index, channel)
+                       (Ptr{Nothing}, Cint, Ref{EncoderInChannel}),
+                       moberg_handle, index, channel))
+        self = new(moberg_handle, index, channel)
         finalizer(close, self)
         self
     end
@@ -23,7 +24,7 @@ function close(ein::EncoderIn)
     DEBUG && println("closing $(ein)")
     checkOK(ccall((:moberg_encoder_in_close, "libmoberg"),
                   Status,
-                  (Moberg, Cint, EncoderInChannel),
+                  (Ptr{Nothing}, Cint, EncoderInChannel),
                   ein.moberg, ein.index, ein.channel))
 end
 
diff --git a/adaptors/julia/MobergIO.jl b/adaptors/julia/MobergIO.jl
index bd65678a91a2a037412f7a734c5d3a12e7b88c82..7c917b8ffae880a03daf27da0c70282fe91f3fe2 100644
--- a/adaptors/julia/MobergIO.jl
+++ b/adaptors/julia/MobergIO.jl
@@ -26,6 +26,7 @@ end
 function close(h::Moberg)
     DEBUG && println("Destroy $(h)")
     ccall((:moberg_free, "libmoberg"), Nothing, (Moberg,), h)
+    h.handle = Ptr{Nothing}(0)
 end
 
 include("AnalogIn.jl")
diff --git a/moberg.c b/moberg.c
index 61d4be5749360aa997c945098e1c1f672e747d9c..72fca0858879516e501f3941df2ab5dde4e81b8e 100644
--- a/moberg.c
+++ b/moberg.c
@@ -38,6 +38,8 @@
 #include <moberg_parser.h>
 
 struct moberg {
+  int should_free;
+  int open_channels;
   struct moberg_config *config;
   struct channel_list {
     int capacity;
@@ -255,19 +257,8 @@ struct moberg *moberg_new()
     fprintf(stderr, "Failed to allocate moberg struct\n");
     goto err;
   }
-  result->analog_in.capacity = 0;
-  result->analog_in.value = NULL;
-  result->analog_out.capacity = 0;
-  result->analog_out.value = NULL;
-  result->digital_in.capacity = 0;
-  result->digital_in.value = NULL;
-  result->digital_out.capacity = 0;
-  result->digital_out.value = NULL;
-  result->encoder_in.capacity = 0;
-  result->encoder_in.value = NULL;
-  result->deferred_action = NULL;
-  result->config = NULL;
-    
+  memset(result, 0, sizeof(*result));
+
   /* Parse default configuration(s) */
   const char * const *config_paths = xdgSearchableConfigDirectories(NULL);
   const char * const *path;
@@ -295,9 +286,9 @@ err:
   return result;
 }
 
-void moberg_free(struct moberg *moberg)
+static void free_if_unused(struct moberg *moberg)
 {
-  if (moberg) {
+  if (moberg->should_free && moberg->open_channels == 0) {
     moberg_config_free(moberg->config);
     channel_list_free(&moberg->analog_in);
     channel_list_free(&moberg->analog_out);
@@ -309,6 +300,15 @@ void moberg_free(struct moberg *moberg)
   }
 }
 
+void moberg_free(struct moberg *moberg)
+{
+  if (moberg) {
+    moberg->should_free = 1;
+    free_if_unused(moberg);
+  }
+}
+
+
 /* Input/output */
 
 struct moberg_status moberg_analog_in_open(
@@ -328,6 +328,7 @@ struct moberg_status moberg_analog_in_open(
   if (! OK(result)) {
     return result;
   }
+  moberg->open_channels++;
   *analog_in = channel->action.analog_in;
   return MOBERG_OK;
 }
@@ -346,6 +347,8 @@ struct moberg_status moberg_analog_in_close(
     return MOBERG_ERRNO(EINVAL);
   }
   struct moberg_status result = channel->close(channel);
+  moberg->open_channels--;
+  free_if_unused(moberg);
   if (! OK(result)) {
     return result;
   }
@@ -369,6 +372,7 @@ struct moberg_status moberg_analog_out_open(
   if (! OK(result)) {
     return result;
   }
+  moberg->open_channels++;
   *analog_out = channel->action.analog_out;
   return MOBERG_OK;
 }
@@ -387,6 +391,8 @@ struct moberg_status moberg_analog_out_close(
     return MOBERG_ERRNO(EINVAL);
   }
   struct moberg_status result = channel->close(channel);
+  moberg->open_channels--;
+  free_if_unused(moberg);
   if (! OK(result)) {
     return result;
   }
@@ -410,6 +416,7 @@ struct moberg_status moberg_digital_in_open(
   if (! OK(result)) {
     return result;
   }
+  moberg->open_channels++;
   *digital_in = channel->action.digital_in;
   return MOBERG_OK;
 }
@@ -428,6 +435,8 @@ struct moberg_status moberg_digital_in_close(
     return MOBERG_ERRNO(EINVAL);
   }
   struct moberg_status result = channel->close(channel);
+  moberg->open_channels--;
+  free_if_unused(moberg);
   if (! OK(result)) {
     return result;
   }
@@ -451,6 +460,7 @@ struct moberg_status moberg_digital_out_open(
   if (! OK(result)) {
     return result;
   }
+  moberg->open_channels++;
   *digital_out = channel->action.digital_out;
   return MOBERG_OK;
 }
@@ -469,6 +479,8 @@ struct moberg_status moberg_digital_out_close(
     return MOBERG_ERRNO(EINVAL);
   }
   struct moberg_status result = channel->close(channel);
+  moberg->open_channels--;
+  free_if_unused(moberg);
   if (! OK(result)) {
     return result;
   }
@@ -492,6 +504,7 @@ struct moberg_status moberg_encoder_in_open(
   if (! OK(result)) {
     return result;
   }
+  moberg->open_channels++;
   *encoder_in = channel->action.encoder_in;
   return MOBERG_OK;
 }
@@ -510,6 +523,8 @@ struct moberg_status moberg_encoder_in_close(
     return MOBERG_ERRNO(EINVAL);
   }
   struct moberg_status result = channel->close(channel);
+  moberg->open_channels--;
+  free_if_unused(moberg);
   if (! OK(result)) {
     return result;
   }