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

Bug#884635: transition: libupnp



Hi,

Unfortunately, there is no porting guide. But the good news is that the new API is pretty much straight forward and I can summarize it here. It is much easier to use than it is to explain, but here it goes:

You no longer have pointers to data structures. All the pointers have been substituted by handlers. This also means that you no longer de-reference pointers, you use functions with meaningful names to access the fields. That was done a long time ago to shield the applications using libupnp from changes in the internal data structures, as well as allowing developers to make changes to these structures without the need to release incompatible libraries.

In the processes, several repetitive bug prone boiler plate code has been replaced by those functions, which being defined as macro templates are no longer subject to this type of mistakes. Just call the function and get what you want.

All the magic is done in the files upnp/inc/TemplateSource.h and upnp/inc/TemplateInclude.h. The technique is called x-macros (https://en.wikipedia.org/wiki/X_Macro), and is as old as the first assembly pre-processor. Together with some of the C preprocessor features, it works like a C++ object. You have classes defined in source files like ActionComplete.h, and the class definition is boiler plate. There are a limited number of types that an object can have, like integer, string, DOMString, buffer, list and object. The last is a handle to another object. There are get and set methods for each member. Every class has a new(), delete(), dup() and assign() methods.

Example. The class ActionComplete is defined like this:

#define CLASS UpnpActionComplete

#define EXPAND_CLASS_MEMBERS(CLASS) \
	EXPAND_CLASS_MEMBER_INT(CLASS, ErrCode, int) \
	EXPAND_CLASS_MEMBER_STRING(CLASS, CtrlUrl) \
	EXPAND_CLASS_MEMBER_INT(CLASS, ActionRequest, IXML_Document *) \
	EXPAND_CLASS_MEMBER_INT(CLASS, ActionResult, IXML_Document *) \

This creates the following methods:

UpnpActionComplete *UpnpActionComplete_new();
void UpnpActionComplete_delete(UpnpActionComplete *p);
UpnpActionComplete *UpnpActionComplete_dup(UpnpActionComplete *p);
UpnpActionComplete *UpnpActionComplete_assign(UpnpActionComplete *p, const UpnpActionComplete *q);

For each INT member field:

int UpnpActionComplete_get_ErrCode(const UpnpActionComplete *p);
int UpnpActionComplete_set_ErrCode(const UpnpActionComplete *p, int n);

For STRING member fields:

const UpnpString *UpnpActionComplete_get_CtrlUrl(const UpnpActionComplete *p);
int UpnpActionComplete_set_CtrlUrl(CLASS *p, const UpnpString *s);
size_t UpnpActionComplete_get_CtrlUrl##_Length(const UpnpActionComplete *p);
const char *UpnpActionComplete_get_CtrlUrl##_cstr(const UpnpActionComplete *p);
int UpnpActionComplete_strcpy_CtrlUrl(UpnpActionComplete *p, const char *s);
int UpnpActionComplete_strncpy_CtrlUrl(UpnpActionComplete *p, const char *s, size_t n);
void UpnpActionComplete_clear_CtrlUrl(UpnpActionComplete *p);

And so on.

There is only one class that is coded in C, and that is UpnpString, which can be found in upnp/src/api/UpnpString.c and upnp/inc/UpnpString.h. There you can see how the template generate code would look like.

If I can help further, please do contact me.

Best regards,
Marcelo.


On Sun, Sep 30, 2018 at 7:40 AM Uwe Kleine-König <uwe@kleine-koenig.org> wrote:
Hello,

adding Marcelo (upstream for libupnp) to recipents.


Reply to: