An interesting hack ?



	For a long time writing Bonobo servers has been far too
difficult, involving lots of boiler plate code, and nastiness.
The attached files implement a possible solution to this that I
would very much appreciate review of - preferable savage
criticism.

	To use it you do:

header:
...
typedef struct {
	BObjectClass                parent;
	POA_Bonobo_UIContainer__epv epv;
} BonoboUIContainerClass;
...

impl:
...
static void
bonobo_ui_container_class_init (GtkObjectClass *klass)
{
	BonoboUIContainerClass *c_klass = (BonoboUIContainerClass
*) klass;
	POA_Bonobo_UIContainer__epv *epv = &c_klass->epv;

	epv->setNode    = impl_Bonobo_UIContainer_setNode;
	epv->getNode    = impl_Bonobo_UIContainer_getNode;
...
}

GtkType
bonobo_ui_container_get_type (void)
{
	static GtkType type = 0;

	if (!type) {
		GtkTypeInfo info = {
			"BonoboUIContainer",
			sizeof (BonoboUIContainer),
			sizeof (BonoboUIContainerClass),
			(GtkClassInitFunc) bonobo_ui_container_class_init,
			(GtkObjectInitFunc) bonobo_ui_container_init,
			NULL, /* reserved 1 */
			NULL, /* reserved 2 */
			(GtkClassInitFunc) NULL
		};

		type = b_type_unique (
			b_object_get_type (),
			POA_Bonobo_UIContainer__init,
			NULL,
			&info);
	}

	return type;
}

	And that is it IE. the only vestige of the CORBA stuff is
typing 4 extra lines ( and filling out the epv in the class
initializer ). To create a new CORBA object you do:

BObject *object = gtk_type_new (BONOBO_TYPE_UI_CONTAINER);
CORBA_Object o = B_OBJECT_GET_CORBA (object);

	To get an object from the servant you do:

BObject *object = B_SERVANT_GET_OBJECT (servant);

	etc.

	I plan to implement a b_object (gpointer p) function that
will safely and reliably detect which type the pointer is and cast it
appropriately and safely to a BObject * [ short of knobbling the IDL
compiler to return BObjects ].


	So - here are the known issues.

	a) Cannot sub-class without adding a new EPV - add a boolean on
	b_type_unique - not a major problem.

	b) Ties us to ORBit - this is already the case, either way we
	could have configure checks for other orbs if / when.

	c) Uses ORB internals - c'est la vie - see b) - ORBit is stable
	also there is space for bin-compat CORBA_Object_struct expansion
	anyway.

	d) The EPV struct has to be the first element in the derived
	class data - life is tough. Note you can easily add your own
	local methods and signals after this.

	e) Adding CORBA methods to the IDL will cause nasty bin-compat
	breakage - we could make the first element of the class structure
	a pointer to the EPV - this would insulate us to an extent.

	Some points for expansion might be:

	* Since we control the CORBA_Object reference, we could do
	something slightly sensible with the current per object epv
	allocation and save lots of space across the system's objects.

	Anyway, feedback much appreciated.

	Bite me please.

		Michael.


federico


Committing to bonobo...

Dude !

	Dude !

		Dude !

	I just build my bonobo and saw:

bonobo-control.c: In function `impl_Bonobo_Control_focus':
bonobo-control.c:477: warning: `direction' might be used uninitialized in
this function

	I appreciate your fixes - but a warning and a really
obvious brokenness:

	switch (corba_direction) {
	case Bonobo_Control_TAB_FORWARD:
		direction = GTK_DIR_TAB_FORWARD;
		break;

	case Bonobo_Control_TAB_BACKWARD:
		corba_direction = GTK_DIR_TAB_BACKWARD;
		break;

	case Bonobo_Control_UP:
		corba_direction = GTK_DIR_UP;
		break;
...
	return gtk_container_focus (GTK_CONTAINER (priv->plug),
				    direction);


	I worry :-) it's a good thing I like a clean build,

	Also:

	/* FIXME: this will not work for local controls. */

	Is this correct ? is this neccessary, why can't we
detect the local case using is_local ? is it really broken ?

	Regards,

		Michael.

-- 
 mmeeks gnu org  <><, Pseudo Engineer, itinerant idiot
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/**
 * b-object.c: B Unknown interface base implementation
 *
 * Authors:
 *   Miguel de Icaza (miguel kernel org)
 *   Michael Meeks (michael helixcode com)
 *
 * Copyright 1999,2000 Helix Code, Inc.
 */

#include <config.h>
#include <stdio.h>
#include <gtk/gtksignal.h>
#include <gtk/gtkmarshal.h>
#include <gtk/gtktypeutils.h>
#include <bonobo/b.h>
#include <bonobo/bonobo-exception.h>
#include <bonobo/bonobo-main.h>
#include <bonobo/bonobo-object.h>
#include "bonobo-running-context.h"
#include "bonobo-object-directory.h"

/* Need to examine how ORBit sets up ORBit_RootObject_struct's
	ORBit_RootObject_Interface* interface; 
	guchar is_pseudo_object;
	gint refs;
*/
#define B_GTK_OBJ_FLAG_PATTERN 0x8000
#define B_GTK_FLAG_PATTERN (GTK_FLOATING | 0x4000)

typedef struct {
	int   ref_count;
	GList *objs;
} BAggregateObject;

struct _BObjectPrivate {
	BAggregateObject *ao;
	int destroy_id;
};

enum {
	QUERY_INTERFACE,
	SYSTEM_EXCEPTION,
	LAST_SIGNAL
};

static guint b_object_signals [LAST_SIGNAL];
static GtkObjectClass *b_object_parent_class;

/* Do not use this function, it is not what you want; see unref */
static void
b_object_destroy (BAggregateObject *ao)
{
	GList *l;

	g_return_if_fail (ao->ref_count > 0);

	for (l = ao->objs; l; l = l->next) {
		GtkObject *o = l->data;

		gtk_signal_disconnect (o, B_OBJECT (o)->priv->destroy_id);
		if (o->ref_count >= 1)
			gtk_object_destroy (GTK_OBJECT (o));
		else
			g_warning ("Serious ref-counting error [%p]", o);
	}
}

static void
b_object_finalize (BAggregateObject *ao)
{
	GList *l;

	g_return_if_fail (ao->ref_count == 0);

	for (l = ao->objs; l; l = l->next) {
		GtkObject *o = GTK_OBJECT (l->data);

		if (!o)
			g_error ("Serious b object corruption");
		else {
			g_assert (B_OBJECT (o)->priv->ao != NULL);

			/*
			 * Disconnect the GTK+ object from the aggregate object
			 * and unref it so that it is possibly finalized ---
			 * other parts of GTK+ may still have references to it.
			 *
			 * The GTK+ object was already destroy()ed in
			 * b_object_destroy().
			 */

			B_OBJECT (o)->priv->ao = NULL;
			gtk_object_unref (o);
		}
	}

	g_list_free (ao->objs);
	ao->objs = NULL;


	g_free (ao);
}

/**
 * b_object_ref:
 * @object: A BObject you want to ref-count
 *
 * increments the reference count for the aggregate BObject.
 */
void
b_object_ref (BObject *object)
{
	g_return_if_fail (B_IS_OBJECT (object));
	g_return_if_fail (object->priv->ao->ref_count > 0);

	object->priv->ao->ref_count++;
}

/**
 * b_object_unref:
 * @object: A BObject you want to unref.
 *
 * decrements the reference count for the aggregate BObject.
 */
void
b_object_unref (BObject *object)
{
	BAggregateObject *ao;

	g_return_if_fail (B_IS_OBJECT (object));

	ao = object->priv->ao;
	g_return_if_fail (ao != NULL);
	g_return_if_fail (ao->ref_count > 0);

	if (ao->ref_count == 1)
		b_object_destroy (ao);

	ao->ref_count--;

	if (ao->ref_count == 0)
		b_object_finalize (ao);
}

static void
impl_B_Unknown_ref (PortableServer_Servant servant, CORBA_Environment *ev)
{
	b_object_ref (B_SERVANT_GET_OBJECT (servant));
}

static void
impl_B_Unknown_unref (PortableServer_Servant servant, CORBA_Environment *ev)
{
	b_object_unref (B_SERVANT_GET_OBJECT (servant));
}

static BObject *
b_object_get_local_interface_from_objref (BObject     *object,
					  CORBA_Object interface)
{
	CORBA_Environment  ev;
	GList             *l;

	if (interface == CORBA_OBJECT_NIL)
		return NULL;

	CORBA_exception_init (&ev);

	for (l = object->priv->ao->objs; l; l = l->next) {
		BObject *tryme = l->data;

		if (CORBA_Object_is_equivalent (
			interface, B_OBJECT_GET_CORBA (tryme), &ev)) {
			CORBA_exception_free (&ev);
			return tryme;
		}

		if (BONOBO_EX (&ev)) {
			CORBA_exception_free (&ev);
			return NULL;
		}

	}

	CORBA_exception_free (&ev);

	return NULL;
}

static BObject *
b_object_query_local_interface (BObject    *object,
				const char *repo_id)
{
	CORBA_Environment  ev;
	BObject      *retval;
	CORBA_Object       corba_retval;
	GtkType            type;
	GList             *l;

	g_return_val_if_fail (B_IS_OBJECT (object), NULL);

	retval       = NULL;
	corba_retval = CORBA_OBJECT_NIL;

	gtk_signal_emit (
		GTK_OBJECT (object), b_object_signals [QUERY_INTERFACE],
		repo_id, &corba_retval);

	CORBA_exception_init (&ev);

	if (! CORBA_Object_is_nil (corba_retval, &ev)) {
		BObject *local_interface;

		local_interface = b_object_get_local_interface_from_objref (
			object, corba_retval);

		if (local_interface != NULL)
			b_object_ref (object);

		return local_interface;
	}

	type = gtk_type_from_name (repo_id);

	/* Try looking at the gtk types */
	for (l = object->priv->ao->objs; l; l = l->next){
		BObject *tryme = l->data;

		if ((type && gtk_type_is_a (GTK_OBJECT (tryme)->klass->type, type)) ||
		    CORBA_Object_is_a (B_OBJECT_GET_CORBA (tryme), (char *) repo_id, &ev)) {
			retval = tryme;
			break;
		}
	}

	if (retval != NULL)
		b_object_ref (object);

	CORBA_exception_free (&ev);

	return retval;
}

static CORBA_Object
impl_B_Unknown_queryInterface (PortableServer_Servant  servant,
			       const CORBA_char       *repoid,
			       CORBA_Environment      *ev)
{
	BObject *object = B_SERVANT_GET_OBJECT (servant);
	BObject *local_interface;

	local_interface = b_object_query_local_interface (
		object, repoid);

	if (local_interface == NULL)
		return CORBA_OBJECT_NIL;

	return CORBA_Object_duplicate (B_OBJECT_GET_CORBA (local_interface), ev);
}


/*
 * FIXME: cut and paste from orbit_object.c: CORBA_Object_release_fn
 */
static void
b_corba_object_free (BObject *object)
{
	CORBA_Object obj = B_OBJECT_GET_CORBA (object);

	g_assert (obj!=NULL);

	bonobo_running_context_remove_object (obj);

	ORBIT_ROOT_OBJECT_UNREF (obj);

	if (ORBIT_ROOT_OBJECT (obj)->refs <= 0) {
		g_hash_table_remove (obj->orb->objrefs, obj);
		
		if (obj->connection)
			giop_connection_unref (obj->connection);

		g_free (obj->object_id);
		ORBit_delete_profiles (obj->profile_list);
		ORBit_delete_profiles (obj->forward_locations);

		g_free (obj->vepv); /* FIXME: what ? */
	}
}

static void
b_object_finalize_real (GtkObject *object)
{
	BObject *b_object = B_OBJECT (object);
	BObjectClass *klass = (BObjectClass *)GTK_OBJECT (object)->klass;
	void *servant = B_OBJECT_GET_SERVANT (b_object);
	CORBA_Environment ev;

	g_assert (b_object->priv->ao == NULL);

	CORBA_exception_init (&ev);

	b_corba_object_free (b_object);

	if (servant) {
		PortableServer_ObjectId *oid;

		oid = PortableServer_POA_servant_to_id (bonobo_poa(), servant, &ev);
		PortableServer_POA_deactivate_object (bonobo_poa (), oid, &ev);

		if (klass->poa_fini_fn)
			klass->poa_fini_fn (servant, &ev);
		else /* Actualy quicker and nicer */
			PortableServer_ServantBase__fini (servant, &ev);

		CORBA_free (oid);
	}
	CORBA_exception_free (&ev);

	g_free (b_object->priv);

	b_object_parent_class->finalize (object);
}

static void
b_object_usage_error (BObject *object)
{
	g_error ("Aggregate b_object member [%p] has been "
		 "destroyed using gtk_object_* methods", object);
}

/**
 * b_object_add_interface:
 * @object: The BObject to which an interface is going to be added.
 * @newobj: The BObject containing the new interface to be added.
 *
 * Adds the interfaces supported by @newobj to the list of interfaces
 * for @object.  This function adds the interfaces supported by
 * @newobj to the list of interfaces support by @object. It should never
 * be used when the object has been exposed to the world. This is a firm
 * part of the contract.
 */
void
b_object_add_interface (BObject *object, BObject *newobj)
{
       BAggregateObject *oldao, *ao;
       GList *l;

       g_return_if_fail (object->priv->ao->ref_count > 0);
       g_return_if_fail (newobj->priv->ao->ref_count > 0);

       if (object->priv->ao == newobj->priv->ao)
               return;

       /*
	* Explanation:
	*   B Objects should not be assembled after they have been
	*   exposed, or we would be breaking the contract we have with
	*   the other side.
	*
	*   This check is not perfect, but might help some people.
	*/

       ao = object->priv->ao;
       oldao = newobj->priv->ao;
       ao->ref_count = ao->ref_count + oldao->ref_count - 1;

       /* Merge the two AggregateObject lists */
       for (l = oldao->objs; l; l = l->next) {
	       BObject *new_if = l->data;

	       /* FIXME: we prolly also want to check for duplicate interfaces */
               if (!g_list_find (ao->objs, new_if)) {
                       ao->objs = g_list_prepend (ao->objs, new_if);

		       new_if->priv->ao = ao;
               } else
		       g_warning ("attempting to merge identical interfaces [%p]", new_if);
       }

       g_assert (newobj->priv->ao == ao);

       g_list_free (oldao->objs);
       g_free (oldao);
}

/**
 * b_object_query_interface:
 * @object: A BObject to be queried for a given interface.
 * @repo_id: The name of the interface to be queried.
 *
 * Returns: The CORBA interface named @repo_id for @object.
 */
Bonobo_Unknown
b_object_query_interface (BObject *object, const char *repo_id)
{
       CORBA_Environment ev;
       CORBA_Object retval;

       CORBA_exception_init (&ev);

       retval = Bonobo_Unknown_queryInterface (
	       B_OBJECT_GET_CORBA (object), (CORBA_char *) repo_id, &ev);

       if (BONOBO_EX (&ev))
               retval = CORBA_OBJECT_NIL;

       CORBA_exception_free (&ev);

       return retval;
}

/**
 * b_object_check_env:
 * @object: The object on which we operate
 * @ev: CORBA Environment to check
 *
 * This routine verifies the @ev environment for any fatal system
 * exceptions.  If a system exception occurs, the object raises a
 * "system_exception" signal.  The idea is that GtkObjects which are
 * used to wrap a CORBA interface can use this function to notify
 * the user if a fatal exception has occurred, causing the object
 * to become defunct.
 */
void
b_object_check_env (BObject *object, CORBA_Object obj, CORBA_Environment *ev)
{
	g_return_if_fail (ev != NULL);
	g_return_if_fail (B_IS_OBJECT (object));

	if (!BONOBO_EX (ev))
		return;

	if (ev->_major == CORBA_SYSTEM_EXCEPTION)
		gtk_signal_emit (
			GTK_OBJECT (object),
			b_object_signals [SYSTEM_EXCEPTION],
			obj, ev);
}

static int
get_refs (BObject *object)
{
	return object->priv->ao->ref_count;
}

static void
dont_release (gpointer obj, CORBA_Environment *ev)
{
	BObject *object = B_CORBA_GET_OBJECT (obj);

	g_warning ("Reference counting error: "
		   "Attempts to release CORBA_Object associated with "
		   "'%s' which still has a reference count of %d",
		   gtk_type_name (obj->klass->type),
		   get_refs (object));
}

static void
do_corba_hacks (BObject      *object,
		BObjectClass *klass)
{
	CORBA_Object obj;
	CORBA_Environment ev;
	static const ORBit_RootObject_Interface ri = { dont_release };

	CORBA_exception_init (&ev);

	object->servant._private = NULL;
	object->servant.vepv     = klass->vepv;

	if (!klass->poa_init_fn) {
		g_warning ("It looks like you used gtk_type_unique "
			   "instead of b_type_unique on type '%s'",
			   gtk_type_name (((GtkObjectClass *)klass)->type));
		return;
	}
	klass->poa_init_fn ((PortableServer_Servant) &object->servant, &ev);
	if (BONOBO_EX (&ev)) {
		g_warning ("Exception initializing servant '%s'",
			   bonobo_exception_get_text (&ev));
		return;
	}

	CORBA_free (PortableServer_POA_activate_object (
		bonobo_poa (), &object->servant, &ev));

	obj = PortableServer_POA_servant_to_reference (
		bonobo_poa (), &object->servant, &ev);

	/* FIXME: this is slightly messy :-) */
	memcpy (&object->object, obj, sizeof (object->object));
	ORBIT_CHUNK_FREE (CORBA_Object, obj);
	object->object.parent.interface = &ri;

	bonobo_running_context_add_object (B_OBJECT_GET_CORBA (object));

	CORBA_exception_free (&ev);
}

static void
b_object_instance_init (GtkObject    *gtk_object,
			GtkTypeClass *klass)
{
	BObject *object = B_OBJECT (gtk_object);

	BAggregateObject *ao;

	object->priv = g_new (BObjectPrivate, 1);
	object->priv->destroy_id = gtk_signal_connect (
		gtk_object, "destroy", GTK_SIGNAL_FUNC (b_object_usage_error),
		NULL);

	object->priv->ao = ao = g_new0 (BAggregateObject, 1);

	ao->objs = g_list_append (object->priv->ao->objs, object);
	ao->ref_count = 1;

	GTK_OBJECT_UNSET_FLAGS (GTK_OBJECT (object), GTK_FLOATING);

	g_warning ("b_object_instance init '%s' '%s'",
		   gtk_type_name (gtk_object->klass->type),
		   gtk_type_name (klass->type));

	do_corba_hacks (object, B_OBJECT_CLASS (klass));
}

static void
b_object_class_init (BObjectClass *klass)
{
	GtkObjectClass *object_class = (GtkObjectClass *) klass;

	b_object_parent_class = gtk_type_class (gtk_object_get_type ());

	b_object_signals [QUERY_INTERFACE] =
		gtk_signal_new ("query_interface",
				GTK_RUN_LAST,
				object_class->type,
				GTK_SIGNAL_OFFSET(BObjectClass,query_interface),
				gtk_marshal_NONE__POINTER_POINTER,
				GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER);
	b_object_signals [SYSTEM_EXCEPTION] =
		gtk_signal_new ("system_exception",
				GTK_RUN_LAST,
				object_class->type,
				GTK_SIGNAL_OFFSET(BObjectClass,system_exception),
				gtk_marshal_NONE__POINTER_POINTER,
				GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER);

	gtk_object_class_add_signals (object_class, b_object_signals, LAST_SIGNAL);

	object_class->finalize = b_object_finalize_real;
}

/**
 * b_object_get_type:
 *
 * Returns: the GtkType associated with the base BObject class type.
 */
GtkType
b_object_get_type (void)
{
	static GtkType type = 0;

	if (!type) {
		GtkTypeInfo info = {
			"BObject",
			sizeof (BObject),
			sizeof (BObjectClass),
			(GtkClassInitFunc) b_object_class_init,
			(GtkObjectInitFunc) b_object_instance_init,
			NULL, /* reserved 1 */
			NULL, /* reserved 2 */
			(GtkClassInitFunc) NULL
		};

		type = gtk_type_unique (
			gtk_object_get_type (), &info);
	}

	return type;
}

static gboolean
setup_type (GtkType type, BPOAFn init_fn, BPOAFn fini_fn)
{
	GtkType       p, b_type;
	int           depth;
	BObjectClass *klass;
	gpointer     *vepv;

	b_type = b_object_get_type ();

	/* How far down the tree are we ? */
	for (depth = 0, p = type; p && p != b_type;
	     p = gtk_type_parent (p))
		depth++;

	if (!type) {
		g_warning ("Trying to inherit '%s' from a BObject, but "
			   "no BObject in the ancestory",
			   gtk_type_name (type));
		return FALSE;
	}

	g_warning ("We are at depth %d with type '%s'",
		   depth, gtk_type_name (type));

	klass = gtk_type_class (type);

	klass->poa_init_fn = init_fn;
	klass->poa_fini_fn = fini_fn;

	klass->epv._private       = NULL;
	klass->epv.ref            = impl_B_Unknown_ref;
	klass->epv.unref          = impl_B_Unknown_unref;
	klass->epv.queryInterface = impl_B_Unknown_queryInterface;
	
	vepv = g_new0 (gpointer, depth + 2);
	klass->vepv = (POA_Bonobo_Unknown__vepv *) vepv;
	klass->vepv->_base_epv = NULL;
	klass->vepv->Bonobo_Unknown_epv = &klass->epv;

	/* Build our EPV */
	if (depth > 0) {
		int i;

		p = type;
		for (i = depth; i > 0; i--) {
			GtkTypeQuery *info;

			p = gtk_type_parent (p);
			info = gtk_type_query (p);
			g_return_val_if_fail (info != NULL, FALSE);

			vepv [i + 1] = ((guchar *)klass) + info->class_size;

			g_free (info);
		}
	}

	return TRUE;
}

GtkType
b_type_unique (GtkType            parent_type,
	       BPOAFn             init_fn,
	       BPOAFn             fini_fn,
	       const GtkTypeInfo *info)
{
	GtkType       type;

	type = gtk_type_unique (parent_type, info);
	if (!type)
		return 0;

	if (setup_type (type, init_fn, fini_fn))
		return type;
	else
		return 0;
}

BObject *
b_object (gpointer p)
{
	if (!p)
		return NULL;

	/* ... do clever stuff here */

	return NULL;
}
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/**
 * B Unknown interface base implementation
 *
 * Authors:
 *   Miguel de Icaza (miguel kernel org)
 *   Michael Meeks (michael helixcode com)
 *
 * Copyright 1999,2000 Helix Code, Inc.
 */
#ifndef _B_OBJECT_H_
#define _B_OBJECT_H_

#include <libgnome/gnome-defs.h>
#include <gtk/gtkobject.h>
#include <bonobo/Bonobo.h>

#include <bonobo/bonobo-object.h>

BEGIN_GNOME_DECLS


#undef B_OBJECT_DEBUG
 
#define B_OBJECT_TYPE        (b_object_get_type ())
#define B_OBJECT(o)          (GTK_CHECK_CAST ((o), B_OBJECT_TYPE, BObject))
#define B_OBJECT_CLASS(k)    (GTK_CHECK_CLASS_CAST((k), B_OBJECT_TYPE, BObjectClass))
#define B_IS_OBJECT(o)       (GTK_CHECK_TYPE ((o), B_OBJECT_TYPE))
#define B_IS_OBJECT_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), B_OBJECT_TYPE))


#define B_OBJECT_HEADER_SIZE (sizeof (GtkObject) + sizeof (BObjectPrivate *))

/*
 * Macros to convert between types.
 *  - foolproof versions to follow.
 */
#define B_OBJECT_GET_CORBA(o)   ((CORBA_Object)&(o)->object)
#define B_OBJECT_GET_SERVANT(o) ((PortableServer_Servant)&(o)->servant)
#define B_CORBA_GET_OBJECT(o)   ((BObject *)((guchar *)(o)				\
					     - B_OBJECT_HEADER_SIZE)
#define B_CORBA_GET_SERVANT(o)  ((BObject *)((guchar *)(o)				\
					     + sizeof (struct CORBA_Object_struct)	\
					     + sizeof (gpointer) * 4))
#define B_SERVANT_GET_CORBA(o)  ((BObject *)((guchar *)(o)				\
					     - sizeof (struct CORBA_Object_struct)	\
					     - sizeof (gpointer) * 4))
#define B_SERVANT_GET_OBJECT(o) ((BObject *)((guchar *)(o)				\
					     - B_OBJECT_HEADER_SIZE			\
					     - sizeof (struct CORBA_Object_struct)	\
					     - sizeof (gpointer) * 4))

typedef struct _BObject             BObject;
typedef struct _BObjectPrivate      BObjectPrivate;
typedef struct _BObjectPrivateClass BObjectPrivateClass;

/* Detects the pointer type and returns the object reference - magic. */
BObject *b_object (gpointer p);

struct _BObject {
	GtkObject                  base;
	/* For the aggregate */
	BObjectPrivate            *priv;

	/* Start: CORBA_Object */
	struct CORBA_Object_struct object;
	gpointer                   bincompat[4]; /* expansion */
	/* End:   CORBA_Object */
	
	/* Start: BonoboObjectServant */
	POA_Bonobo_Unknown         servant;
	int                        flags;         /* discriminant */
	/* End:   BonoboObjectServant */

	/* User data ... */
};

typedef void (*BPOAFn) (PortableServer_Servant servant,
			CORBA_Environment     *ev);

typedef struct {
	GtkObjectClass             parent_class;

	/* signals */
	void  (*query_interface)  (BObject           *object,
				   const char        *repo_id,
				   CORBA_Object      *retval);
	void  (*system_exception) (BObject           *object,
				   CORBA_Object       cobject,
				   CORBA_Environment *ev);

	BPOAFn                     poa_init_fn;
	BPOAFn                     poa_fini_fn;

	BObjectPrivateClass       *priv;

	POA_Bonobo_Unknown__vepv  *vepv;

	POA_Bonobo_Unknown__epv    epv;

	/* Inherited vpev methods ... */
} BObjectClass;

GtkType        b_object_get_type        (void);
GtkType        b_type_unique            (GtkType            parent_type,
					 BPOAFn             init_fn,
					 BPOAFn             fini_fn,
					 const GtkTypeInfo *info);
BObject       *b_object_construct       (BObject           *object,
					 CORBA_Object       corba_object);
void           b_object_add_interface   (BObject           *object,
					 BObject           *newobj);
Bonobo_Unknown b_object_query_interface (BObject           *object,
					 const char        *repo_id);
void           b_object_check_env       (BObject           *object,
					 CORBA_Object       obj,
					 CORBA_Environment *ev);
void           b_object_ref             (BObject           *object);
void           b_object_unref           (BObject           *object);

END_GNOME_DECLS

#endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]