Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gnome-python/gnome-python/ChangeLog,v
retrieving revision 1.161
diff -u -p -r1.161 ChangeLog
--- ChangeLog	20 Nov 2003 15:56:11 -0000	1.161
+++ ChangeLog	25 Nov 2003 18:26:56 -0000
@@ -1,3 +1,20 @@
+2003-11-25  Gustavo J. A. M. Carneiro  <gustavo@users.sourceforge.net>
+
+	* examples/bonobo/unknown.py: Example of how to implement a
+	Bonobo::Unknown servant using bonobo.UnknownBaseImpl as "mixin"
+	class.  It also serves as testbed for further debugging.
+
+	* bonobo/__init__.py: Define a base class, UnknownBaseImpl, do
+	help creation of Bonobo::Unknown compliant servants, and allow
+	such servants to be aggregated with BonoboObject based servants.
+
+	* bonobo/bonobo.defs: wrap bonobo_object_ref/unref.
+
+	* bonobo/bonobo-types.defs (ForeignObject): Declare type
+	BonoboForeignObject.
+
+	* bonobo/bonobo.override: #include <bonobo/bonobo-foreign-object.h>
+
 2003-11-20  James Henstridge  <james@daa.com.au>
 
 	* gconf/gconf.override: ignore the set_car/cdr_nocopy variants.
Index: bonobo/__init__.py
===================================================================
RCS file: /cvs/gnome/gnome-python/gnome-python/bonobo/__init__.py,v
retrieving revision 1.5
diff -u -p -r1.5 __init__.py
--- bonobo/__init__.py	1 Nov 2002 02:25:49 -0000	1.5
+++ bonobo/__init__.py	25 Nov 2003 18:26:56 -0000
@@ -10,3 +10,25 @@ del ORBit
 import activation
 
 from _bonobo import *
+
+class UnknownBaseImpl(object):
+    def __init__(self):
+        self.__bobj = ForeignObject(self._this())
+	self.__bobj.connect("destroy", self.__destroy)
+    def get_bonobo_object(self):
+        return self.__bobj
+    def ref(self):
+        self.__bobj.ref()
+    def unref(self):
+        self.__bobj.unref()
+    def queryInterface(self, repoid):
+        return self.__bobj.query_local_interface(repoid).corba_objref()
+    def __destroy(self, foreign):
+	# print "Deactivating Object"
+	poa = self._default_POA()
+	id  = poa.servant_to_id(self)
+	poa.deactivate_object(id)
+	# print "Removing reference to ForeignObject"
+	self.__bobj = None
+	# print "Deactivating Object Done"
+
Index: bonobo/bonobo-types.defs
===================================================================
RCS file: /cvs/gnome/gnome-python/gnome-python/bonobo/bonobo-types.defs,v
retrieving revision 1.6
diff -u -p -r1.6 bonobo-types.defs
--- bonobo/bonobo-types.defs	26 Jan 2003 19:37:44 -0000	1.6
+++ bonobo/bonobo-types.defs	25 Nov 2003 18:26:56 -0000
@@ -23,6 +23,13 @@
   (gtype-id "BONOBO_TYPE_ITEM_HANDLER")
 )
 
+(define-object ForeignObject
+  (in-module "Bonobo")
+  (parent "BonoboObject")
+  (c-name "BonoboForeignObject")
+  (gtype-id "BONOBO_TYPE_FOREIGN_OBJECT")
+)
+
 (define-object Listener
   (in-module "Bonobo")
   (parent "BonoboObject")
Index: bonobo/bonobo.defs
===================================================================
RCS file: /cvs/gnome/gnome-python/gnome-python/bonobo/bonobo.defs,v
retrieving revision 1.8
diff -u -p -r1.8 bonobo.defs
--- bonobo/bonobo.defs	3 Aug 2003 19:14:22 -0000	1.8
+++ bonobo/bonobo.defs	25 Nov 2003 18:26:57 -0000
@@ -1130,6 +1130,18 @@
   )
 )
 
+(define-method ref
+  (of-object "BonoboObject")
+  (c-name "bonobo_object_ref")
+  (return-type "none")
+)
+
+(define-method unref
+  (of-object "BonoboObject")
+  (c-name "bonobo_object_unref")
+  (return-type "none")
+)
+
 (define-method query_interface
   (of-object "BonoboObject")
   (c-name "bonobo_object_query_interface")
@@ -2376,4 +2388,13 @@
   )
 )
 
+;; From bonobo-foreign-object.h
+(define-function bonobo_foreign_object_new
+  (c-name "bonobo_foreign_object_new")
+  (is-constructor-of BonoboForeignObject)
+  (return-type "BonoboObject*")
+  (parameters
+   '("CORBA_Object" "corba_objref")
+   )
+)
 
Index: bonobo/bonobo.override
===================================================================
RCS file: /cvs/gnome/gnome-python/gnome-python/bonobo/bonobo.override,v
retrieving revision 1.17
diff -u -p -r1.17 bonobo.override
--- bonobo/bonobo.override	5 Aug 2003 11:02:43 -0000	1.17
+++ bonobo/bonobo.override	25 Nov 2003 18:26:57 -0000
@@ -9,6 +9,8 @@ headers
 #include <libbonobo.h>
 #include <bonobo/bonobo-persist-client.h>
 #include <bonobo/bonobo-item-handler.h>
+#include <bonobo/bonobo-foreign-object.h>
+
 %%
 modulename bonobo
 %%
Index: examples/bonobo/unknown.py
===================================================================
RCS file: examples/bonobo/unknown.py
diff -N examples/bonobo/unknown.py
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ examples/bonobo/unknown.py	25 Nov 2003 18:26:57 -0000
@@ -0,0 +1,72 @@
+#! /usr/bin/env python
+import pygtk; pygtk.require("2.0")
+
+import bonobo
+import Bonobo
+import Bonobo__POA
+import CORBA, sys
+import gc
+
+gc.set_debug(gc.DEBUG_LEAK)
+
+orb = CORBA.ORB_init(sys.argv)
+bonobo.activate()
+
+class PersistStream(Bonobo__POA.PersistStream, bonobo.UnknownBaseImpl):
+    def __init__(self):
+        bonobo.UnknownBaseImpl.__init__(self)
+
+    # implementations of methods/attributes of "Interface" go here
+
+    def load(self, content_type):
+	print "PersistStream::load(content_type='%s')" % content_type
+
+    def save(self, content_type):
+	print "PersistStream::save(content_type='%s')" % content_type
+
+
+ps = PersistStream()
+
+def foo(*args):
+    print args
+
+listener = bonobo.Listener(foo)
+listener.add_interface(ps.get_bonobo_object())
+
+del ps
+## How is it that the PersistStream servant instance is kept alive, I
+## hear you ask?
+##     Well, there's a signal connection from the 'destroy' signal of
+## the ForeignObject to a bound method of the servant instance.  A
+## bound method object contains an implicit reference to the instance
+## to which it is bound.  On the other hand, the servant contains a
+## reference to the ForeignObject.  This way, these two objects keep
+## each other alive with mutual references.
+##     When the 'destroy' signal is fired (when bonobo reference count
+## drops to zero), the bound method in the servant is called, and it
+## deletes the reference it has to the ForeignObject, thus destroying
+## the signal connection (closure), consequently releasing the last
+## reference to the servant.  At least that's my theory on how things
+## work..
+
+
+print "server-side boundary"
+listener = listener.corba_objref() # from now on we work on client-side
+gc.collect()
+print "client-side"
+
+print "query PersistStream"
+ps = listener.queryInterface("IDL:Bonobo/PersistStream:1.0")
+print ps
+print "unref PersistStream"
+if ps is not None:
+    ps.unref()
+gc.collect()
+
+print ">>unref listener start"
+# this should trigger final ref count -> destroy
+listener.unref()
+del listener
+print "<<unref listener end"
+gc.collect()
+
