Proposal for an extended callbacks field

Augie Fackler lists at durin42.com
Tue Jul 24 21:15:17 EDT 2007


Folks,

My summer of code student (Andreas Monitzer) has hit a snag in  
extending the protocol plugin for XMPP because of the design of the  
callbacks. I know that a full reworking of the callback system can't  
happen until libpurple 3.0, so we'd like to propose a solution that  
would patch over this problem in the interim. The proposal is below.  
We'll implement the change, naturally, but I thought it prudent to  
discuss the design some and get feedback before using one of the  
reserved padding pointers and going to  the effort to implement the fix.

Thanks,
Augie Fackler

_The Problem_

Libpurple uses a static struct to describe the callbacks that define  
a prpl (this is only an excerpt):

struct _PurplePluginProtocolInfo
{
   void (*set_info)(PurpleConnection *, const char *info);
   unsigned int (*send_typing)(PurpleConnection *, const char *name,  
PurpleTypingState state);
   void (*get_info)(PurpleConnection *, const char *who);
   void (*set_status)(PurpleAccount *account, PurpleStatus *status);

   void (*set_idle)(PurpleConnection *, int idletime);
   void (*change_passwd)(PurpleConnection *, const char *old_pass,
    const char *new_pass);
   void (*add_buddy)(PurpleConnection *, PurpleBuddy *buddy,  
PurpleGroup *group);
   void (*add_buddies)(PurpleConnection *, GList *buddies, GList  
*groups);

   /* room list serialize */
   char *(*roomlist_room_serialize)(PurpleRoomlistRoom *room);

   void (*_purple_reserved1)(void);
   void (*_purple_reserved2)(void);
   void (*_purple_reserved3)(void);
   void (*_purple_reserved4)(void);
};

This works fine as long as you don't want to change anything. One  
important thing to be careful about is to not change the struct's  
size, if you don't want to force the plugin devs to recompile their  
work. This means that adding new callbacks is limited to four  
functions right now. Since this is very little, Sean tries to avoid  
adding things at any cost, effectively nullifying the ability to add  
new callbacks. This has already added a workaround for setting the  
registration callback for XMPP, where an additional function outside  
this struct is used. This creates a problematic inconsistency that  
complicates the use of the libpurple API for newcomers.


_The Solution_

The proposed solution would use a hashtable, mapping char * -> void  
(*)(...):

struct _PurplePluginProtocolInfo
{
	...
	
	GHashTable *additional_functions;
	void (*_purple_reserved1)(void);
	void (*_purple_reserved2)(void);
	void (*_purple_reserved3)(void);
};

Callbacks other than the ones listed in the struct directly would  
then be added to the hashtable, therefore preventing any further need  
to spend precious padding pointers on callback functions. This allows  
further growth of the library without having to run the risk of  
binary incompatibilities or requiring inconsistent hacks.


_Conclusion_

This solution will solve the issue at hand until a larger update can  
be done (like libpurple 3.0). Sean told us that libpurple is planned  
to move to GObject then, so things will have to be reevaluated at  
that point. However, setting the callbacks in stone stands in the way  
of enhancements to the libpurple library, and thus should be avoided.  
However, it is possible to fix that in the current code, without  
sacrificing binary compatibility.





More information about the Devel mailing list