Page 1 of 1

Motivation of interfaces

Posted: Tue May 28, 2013 8:30 pm
by jaokim
With AmigaOS 4 we got libraries with interfaces. What was the motivation behind adding this extra layer?
I think it is nice to be able to f.i. like in exec.library have a debug interface, but most of the time as a developer using a library, it only adds two extra GetIface/DropIface calls, together with a interface pointer to keep track of, besides the library pointer. Furthermore, not only do I need to keep track of the library's name, but also know if it has a "main" interface or if this particular library calls it something else.

Besides the debug interface of exec, I've yet to find any real usage of it. The application.library has two interfaces: "application" and "prefsobject", but I don't see the real advantage here.

Re: Motivation of interfaces

Posted: Tue May 28, 2013 10:04 pm
by salass00
@jaokim

The main reason is to have separate entry points for legacy (M68k) and native (PPC) programs so that the native programs do not have to adhere to obsolete M68k calling conventions as in another OS. Other advantages include less namespace pollution, limited OO-like capabilities (used f.e. by AmiDock dockies system and PCI interface in expansion.library) and so on.

The interface system also provides a strict versioning scheme so a library can export several incompatible versions of the same interface (older interface versions may have compatibility cludges f.e. that are not needed in newer ones that will only be used by newer programs).

FWIW to make it less work to open and close library interfaces when creating the TuneNet UADE plugin I created functions OpenInterface() and CloseInterface() which combine the effects of OpenLibrary()/CloseLibrary() and GetInterface()/DropInterface() into two easy to use functions:

Code: Select all

static APTR OpenInterface (CONST_STRPTR lib_name, int32 lib_vers,
	CONST_STRPTR int_name, int32 int_vers)
{
	struct Library *library;
	struct Interface *interface;
	library = IExec->OpenLibrary(lib_name, lib_vers);
	if (library) {
		interface = IExec->GetInterface(library, int_name, int_vers, NULL);
		if (interface) {
			return interface;
		}
		IExec->CloseLibrary(library);
	}
	return NULL;
}

static void CloseInterface (APTR interface) {
	if (interface) {
		struct Library *library = ((struct Interface *)interface)->Data.LibBase;
		IExec->DropInterface(interface);
		IExec->CloseLibrary(library);
	}
}

static BOOL OpenLibs (void) {
	if ((IDOS = OpenInterface("dos.library", 52, "main", 1)) &&
		(IUtility = OpenInterface("utility.library", 52, "main", 1)) &&
		(INewlib = OpenInterface("newlib.library", 52, "main", 1)))
	{
		IXpk = OpenInterface("xpkmaster.library", 5, "main", 1);
		IXfd = OpenInterface("xfdmaster.library", 39, "main", 1);
		return TRUE;
	}
	CloseLibs();
	return FALSE;
}

static void CloseLibs (void) {
	CloseInterface(IXfd);
	CloseInterface(IXpk);
	CloseInterface(INewlib);
	CloseInterface(IUtility);
	CloseInterface(IDOS);
}