Language Wrappers

From The Foundry MODO SDK wiki
Revision as of 19:12, 7 December 2017 by Shf (Talk | contribs) (Exported Objects)

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.



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.


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.


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.


These are three stages for implementing your language wrapper.

Exported Objects

Exported objects are objects in modo that can be used by plug-ins. Services, for example, are objects implemented entirely in modo which provide methods that can be called by the client plug-in. You will need to create objects in your language that translate method calls so that they call into the service interface.

When a module is loaded it can present a NeedContext Interface. If that's present it gets called with the GUIDService Interface for the app. Any other service can be found by querying this object for that service interface GUID. The reason the GUIDService specifically is used is so that GUID pointers can be looked up using strings if that's necessary for your language.

Exporting Objects

Objects in your language, exported as COM for nexus.

Loading Plug-ins

Use ours, or roll your own.