Language Wrappers

From The Foundry MODO SDK wiki
Jump to: navigation, search

So you want to write a language wrapper for something other than C++? Good for you! This is an extremely challenging task, but can be very rewarding when it starts to actually work. This question doesn't come up very often and it's quite an advanced topic, so I won't be providing a lot of direct examples or technical help. This is more of an overview of the interesting features of the system and what's required to make a wrapper.

Background

COM

Objects in the SDK are all COM at their core. Object pointers passed from nexus to the plug-in are COM IUnknown interfaces, and object pointers passed back from the plug-in to nexus are exactly the same. The SDK ILxUnknown interface is identical to COM's IUnknown, and the SDK LxResult code is the same as COM's HRESULT.

That said, all the actual interfaces implemented in nexus are unique and don't reuse any other COM idioms. You will be required to translate your object format to use nexus interfaces.

Modules

Plug-in files get loaded as modules. That means that we look for a server of class Loader which can load objects of type Module. Module Objects are loaded opaquely and cached by the host subsystem. When we find a server that we want to use, the Module::Generate() method is used to spawn an instance, which will be -- of course -- a COM object.

The first time a module is loaded -- if the module is unknown at startup or the user uses "Add Plug-in" -- we query for a TagDescription Interface. We enumerate the tags for "server" tags that declare the contents of the module in terms of a class GUID and server name. Each newly-added server is then spawned and queried for its own TagDescription interface. This is enumerated to get the tags for the server itself. The server spawned for tags is then immediately destroyed.

Both the module and the server can present a NeedContext Interface. If present this will be called with the context object, which can be queried for services.

The built-in module loader will load any DLL on Windows or dyso on OSX which contains an entry point called _ILxModule_Create. That function is called with no argument and returns the module object for the DLL.

Caveats

There are some subtle differences between nexus COM and Microsoft COM. Our GUID for IUnknown is different. Fortunately you rarely query for IUnknown, and modo never does, so that's not much of an issue. Our error code defines are also different from standard HRESULT values. This is a bit more of a problem, and if you're using actual COM you'll need to provide a translation.

Stages

These are three stages for implementing your language wrapper.

Importing Objects

Objects from nexus, start with a service.

Exporting Objects

Objects in your language, exported as COM for nexus.

Loading Plug-ins

Use ours, or roll your own.