|
From: Chris F. <cd...@fo...> - 2012-06-05 23:51:03
|
On Tue, Jun 05, 2012 at 07:29:58PM -0400, Chris Frey wrote:
> If MysteryFunction() does not exist, then I need to use a serious hack,
> and wrap the Error object in another struct, so that the OSyncError pointer
> can change at will.
Just to give an impression of the hack, it's below. And yes, this does
fix the issue demonstrated by this script:
------------
#!/usr/bin/python
import opensync1
e = opensync1.Error("First error msg")
print e.print_stack()
e.set_error(opensync1.ERROR_GENERIC, "Second error msg")
print e.get_msg()
print e.print_stack()
------------
Output should be:
ROOT CAUSE: "First error msg"
Second error msg
NEXT ERROR: "Second error msg"
ROOT CAUSE: "First error msg"
But without the patch below, it shows:
ROOT CAUSE: "First error msg"
First error msg
ROOT CAUSE: "First error msg"
- Chris
diff --git a/sources/opensync/wrapper/opensync-error.i b/sources/opensync/wrapper/opensync-error.i
index 71ea33d..dd73b7b 100644
--- a/sources/opensync/wrapper/opensync-error.i
+++ b/sources/opensync/wrapper/opensync-error.i
@@ -1,63 +1,100 @@
typedef struct {} Error;
%feature("exceptionclass") Error;
%extend Error {
+ /*
+ * Hackery notice: we currently wrap the Error pointer (which is
+ * a typedef of OSyncError) inside an ErrorWrapper struct, defined
+ * in the header section of opensync.i. This wrapper struct is
+ * used to hold the real Error pointer, which can change at will
+ * due to some opensync API calls. We then cast the ErrorWrapper
+ * pointer back to an Error pointer and pass it back into the
+ * Python workings, to use as the PyCObject void pointer.
+ * We cast it back to ErrorWrapper when we need to use it.
+ *
+ * If there were a way to extract the PyObject from the PyCObject,
+ * then this hackery would not be necessary. Unfortunately, I don't
+ * know how, or if it is possible. - cdf
+ *
+ * The ErrorWrapper pointers are named 'eww' in honour of its hackery.
+ */
+
/* called by python-module plugin */
Error(PyObject *obj) {
- Error *error = PyCObject_AsVoidPtr(obj);
- osync_error_ref(&error);
- return error;
+ ErrorWrapper *eww = calloc(1, sizeof(ErrorWrapper));
+ ErrorWrapper *other = PyCObject_AsVoidPtr(obj);
+ eww->error = other->error;
+ osync_error_ref(&eww->error);
+ return (Error*) eww;
}
Error(const char *msg, ErrorType type=OSYNC_ERROR_GENERIC) {
- Error *error = NULL;
- osync_error_set(&error, type, "%s", msg);
- return error;
+ ErrorWrapper *ew = calloc(1, sizeof(ErrorWrapper));
+ osync_error_set(&ew->error, type, "%s", msg);
+ return (Error*) ew;
}
~Error() {
- osync_error_unref(&self);
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ osync_error_unref(&eww->error);
+ free(eww);
}
const char *get_name() {
- return osync_error_get_name(&self);
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ return osync_error_get_name(&eww->error);
}
bool is_set() {
- return osync_error_is_set(&self);
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ return osync_error_is_set(&eww->error);
}
ErrorType get_type() {
- return osync_error_get_type(&self);
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ return osync_error_get_type(&eww->error);
}
void set_type(ErrorType type) {
- osync_error_set_type(&self, type);
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ osync_error_set_type(&eww->error, type);
}
const char *get_msg() { // 'print' is a reserved word
- return osync_error_print(&self);
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ return osync_error_print(&eww->error);
}
char *print_stack() {
- return osync_error_print_stack(&self);
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ return osync_error_print_stack(&eww->error);
}
void set_from_error(Error *source) {
- osync_error_set_from_error(&self, &source);
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ ErrorWrapper *ewwsource = (ErrorWrapper*) source;
+ osync_error_set_from_error(&eww->error, &ewwsource->error);
}
- void set(ErrorType type, const char *msg) {
- osync_error_set(&self, type, "%s", msg);
+ void set_error(ErrorType type, const char *msg) {
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ osync_error_set(&eww->error, type, "%s", msg);
}
void stack(Error *child) {
- osync_error_stack(&self, &child);
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ osync_error_stack(&eww->error, &child);
}
Error *get_child() {
- Error *ret = osync_error_get_child(&self);
- if (ret)
+ ErrorWrapper *eww = (ErrorWrapper*) self;
+ Error *ret = osync_error_get_child(&eww->error);
+ if (ret) {
+ /* Hackery: memory leak */
+ eww = calloc(1, sizeof(ErrorWrapper));
osync_error_ref(&ret);
+ eww->error = ret;
+ return (Error*) eww;
+ }
return ret;
}
diff --git a/sources/opensync/wrapper/opensync.i b/sources/opensync/wrapper/opensync.i
index 2e5edd4..2c2347d 100644
--- a/sources/opensync/wrapper/opensync.i
+++ b/sources/opensync/wrapper/opensync.i
@@ -56,6 +56,11 @@ typedef OSyncXMLField XMLField;
typedef OSyncXMLFieldList XMLFieldList;
typedef OSyncXMLFormat XMLFormat;
+/* struct wrapper for OSyncError, since the API can change the actual pointer*/
+typedef struct {
+ Error *error;
+} ErrorWrapper;
+
/* make SWIG treat osync_bool as real Python booleans */
typedef osync_bool bool;
#define true TRUE
|