diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm
index 57aabe31b..26acb564c 100644
--- a/lib/Slic3r.pm
+++ b/lib/Slic3r.pm
@@ -196,6 +196,7 @@ sub thread_cleanup {
     *Slic3r::Flow::DESTROY                  = sub {};
     *Slic3r::GCode::AvoidCrossingPerimeters::DESTROY = sub {};
     *Slic3r::GCode::PlaceholderParser::DESTROY = sub {};
+    *Slic3r::GCode::Wipe::DESTROY           = sub {};
     *Slic3r::GCode::Writer::DESTROY         = sub {};
     *Slic3r::Geometry::BoundingBox::DESTROY = sub {};
     *Slic3r::Geometry::BoundingBoxf::DESTROY = sub {};
diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm
index f8388568b..38374975d 100644
--- a/lib/Slic3r/GCode.pm
+++ b/lib/Slic3r/GCode.pm
@@ -42,7 +42,7 @@ sub set_extruders {
     $self->writer->set_extruders($extruder_ids);
     
     # enable wipe path generation if any extruder has wipe enabled
-    $self->wipe->enable(defined first { $self->config->get_at('wipe', $_) } @$extruder_ids);
+    $self->wipe->set_enable(defined first { $self->config->get_at('wipe', $_) } @$extruder_ids);
 }
 
 sub set_origin {
@@ -54,7 +54,7 @@ sub set_origin {
         scale ($self->origin->y - $pointf->y),  #-
     );
     $self->last_pos->translate(@translate);
-    $self->wipe->path->translate(@translate) if $self->wipe->path;
+    $self->wipe->path->translate(@translate) if $self->wipe->has_path;
     
     $self->origin($pointf);
 }
@@ -99,7 +99,7 @@ sub change_layer {
     $gcode .= $self->writer->travel_to_z($z, 'move to next layer (' . $self->layer_index . ')');
     
     # forget last wiping path as wiping after raising Z is pointless
-    $self->wipe->path(undef);
+    $self->wipe->reset_path;
     
     return $gcode;
 }
@@ -208,7 +208,7 @@ sub extrude_loop {
     # reset acceleration
     $gcode .= $self->writer->set_acceleration($self->config->default_acceleration);
     
-    $self->wipe->path($paths[0]->polyline->clone) if $self->wipe->enable;  # TODO: don't limit wipe to last path
+    $self->wipe->set_path($paths[0]->polyline->clone) if $self->wipe->enable;  # TODO: don't limit wipe to last path
     
     # make a little move inwards before leaving loop
     if ($paths[-1]->role == EXTR_ROLE_EXTERNAL_PERIMETER && defined $self->layer && $self->config->perimeters > 1) {
@@ -333,7 +333,7 @@ sub _extrude_path {
             $self->config->gcode_comments ? " ; $description" : "");
 
         if ($self->wipe->enable) {
-            $self->wipe->path($path->polyline->clone);
+            $self->wipe->set_path($path->polyline->clone);
             $self->wipe->path->reverse;
         }
     }
@@ -429,7 +429,7 @@ sub retract {
     my $gcode = "";
     
     # wipe (if it's enabled for this extruder and we have a stored wipe path)
-    if ($self->config->get_at('wipe', $self->writer->extruder->id) && $self->wipe->path) {
+    if ($self->config->get_at('wipe', $self->writer->extruder->id) && $self->wipe->has_path) {
         $gcode .= $self->wipe->wipe($self, $toolchange);
     }
     
@@ -555,13 +555,11 @@ sub post_toolchange {
 }
 
 package Slic3r::GCode::Wipe;
-use Moo;
+use strict;
+use warnings;
 
 use Slic3r::Geometry qw(scale);
 
-has 'enable'            => (is => 'rw', default => sub { 0 });
-has 'path'              => (is => 'rw');
-
 sub wipe {
     my ($self, $gcodegen, $toolchange) = @_;
     
@@ -609,7 +607,7 @@ sub wipe {
         $gcodegen->writer->extruder->set_retracted($gcodegen->writer->extruder->retracted + $retracted);
         
         # prevent wiping again on same path
-        $self->path(undef);
+        $self->reset_path;
     }
     
     return $gcode;
diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm
index 3196eb320..2abad09b6 100644
--- a/xs/lib/Slic3r/XS.pm
+++ b/xs/lib/Slic3r/XS.pm
@@ -217,6 +217,7 @@ for my $class (qw(
         Slic3r::Flow
         Slic3r::GCode::AvoidCrossingPerimeters
         Slic3r::GCode::PlaceholderParser
+        Slic3r::GCode::Wipe
         Slic3r::Geometry::BoundingBox
         Slic3r::Geometry::BoundingBoxf
         Slic3r::Geometry::BoundingBoxf3
diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp
index b21a9eca7..bdc822090 100644
--- a/xs/src/libslic3r/GCode.cpp
+++ b/xs/src/libslic3r/GCode.cpp
@@ -67,4 +67,25 @@ AvoidCrossingPerimeters::travel_to(Point point, const Pointf &gcodegen_origin,
 REGISTER_CLASS(AvoidCrossingPerimeters, "GCode::AvoidCrossingPerimeters");
 #endif
 
+Wipe::Wipe()
+    : enable(false)
+{
+}
+
+bool
+Wipe::has_path()
+{
+    return !this->path.points.empty();
+}
+
+void
+Wipe::reset_path()
+{
+    this->path = Polyline();
+}
+
+#ifdef SLIC3RXS
+REGISTER_CLASS(Wipe, "GCode::Wipe");
+#endif
+
 }
diff --git a/xs/src/libslic3r/GCode.hpp b/xs/src/libslic3r/GCode.hpp
index a9af44781..a44fce616 100644
--- a/xs/src/libslic3r/GCode.hpp
+++ b/xs/src/libslic3r/GCode.hpp
@@ -35,6 +35,17 @@ class AvoidCrossingPerimeters {
     MotionPlanner* _layer_mp;
 };
 
+class Wipe {
+    public:
+    bool enable;
+    Polyline path;
+    
+    Wipe();
+    bool has_path();
+    void reset_path();
+    //std::string wipe(GCode &gcodegen, bool toolchange = false);
+};
+
 }
 
 #endif
diff --git a/xs/xsp/GCode.xsp b/xs/xsp/GCode.xsp
index 007b2b164..ec939a8b6 100644
--- a/xs/xsp/GCode.xsp
+++ b/xs/xsp/GCode.xsp
@@ -29,3 +29,21 @@
     void set_disable_once(bool value)
         %code{% THIS->disable_once = value; %};
 };
+
+%name{Slic3r::GCode::Wipe} class Wipe {
+    Wipe();
+    ~Wipe();
+    
+    bool has_path();
+    void reset_path();
+    
+    bool enable()
+        %code{% RETVAL = THIS->enable; %};
+    void set_enable(bool value)
+        %code{% THIS->enable = value; %};
+    
+    Ref<Polyline> path()
+        %code{% RETVAL = &(THIS->path); %};
+    void set_path(Polyline* value)
+        %code{% THIS->path = *value; %};
+};
diff --git a/xs/xsp/my.map b/xs/xsp/my.map
index fb1288990..d594ceacd 100644
--- a/xs/xsp/my.map
+++ b/xs/xsp/my.map
@@ -174,6 +174,10 @@ AvoidCrossingPerimeters*         O_OBJECT_SLIC3R
 Ref<AvoidCrossingPerimeters>     O_OBJECT_SLIC3R_T
 Clone<AvoidCrossingPerimeters>   O_OBJECT_SLIC3R_T
 
+Wipe*         O_OBJECT_SLIC3R
+Ref<Wipe>     O_OBJECT_SLIC3R_T
+Clone<Wipe>   O_OBJECT_SLIC3R_T
+
 MotionPlanner*             O_OBJECT_SLIC3R
 Ref<MotionPlanner>         O_OBJECT_SLIC3R_T
 Clone<MotionPlanner>       O_OBJECT_SLIC3R_T
diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt
index 53e021337..675da7beb 100644
--- a/xs/xsp/typemap.xspt
+++ b/xs/xsp/typemap.xspt
@@ -129,6 +129,10 @@
 %typemap{Ref<AvoidCrossingPerimeters>}{simple};
 %typemap{Clone<AvoidCrossingPerimeters>}{simple};
 
+%typemap{Wipe*};
+%typemap{Ref<Wipe>}{simple};
+%typemap{Clone<Wipe>}{simple};
+
 
 %typemap{Points};
 %typemap{Pointfs};