SDK:Tutorial Module Main

From Vectorworks Developer
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

.SDK|SDK ..SDK:Types|SDK Types ..SDK:Using the SDK|Using the SDK ..VCOM:VCOM (Vectorworks Component Object Model)|VCOM Basics ..VCOM:Class Reference|VCOM Class Reference

By Vladislav Stanev

Prev: Tutorial Basics | Next: An Extension Implementation

VCOM

The most fundamental part in the communication between Vectorworks and a plug-in is VCOM (Vectorworks Component Object Model). Its concept is very similar to Microsoft's COM.

The fundamental part of VCOM are interfaces. This is a pure virtual class in C++ provided in the SDK. Each VCOM interface has two main parts:

  • the interface definition -- the pure virtual class containing the functions provided by this interface;
  • and the interface identifier -- provided as a constant with the interface. This is the unique number that identifies exactly this interface, and no other.

A module plug-in is basically a container of interface implementation -- the actual functions that are going to get called when a call is made through the interface. Vectorworks is also like a module, it provides interface implementation.

The Client

Then every module (including Vectorworks) can query interface implementation. This is pretty much like operator 'new' that allocates memory for a particular type. For example if a module wants to call an interface, first it needs to create an instance of it, call the function of the instance, and then delete the instance -- like operator 'delete'.

// 1. Create an instance of an interface identified by the Interface Identifier (IID_)
//    this is pretty much like this:
//
//    ISomeInterface* instance = new IID_SomeInterface;

VCOMPtr<ISomeInterface> instance( IID_SomeInterface );

// 2. Call the function of the interface

instance->Function();

// 3. Free the memory used by the variable
//    The free actually happens in the destructor of the 'VCOMPtr' class
//    but it is essentially like this:
//
//    delete instance;

The most important part here is that the client requests an instance of an interface identifying it by its IID_. The instance is actually returned as a pointer to the interface (pure virtual class), this way the client has no idea how it is actually implemented. All it matters for the client is what functions are there to call.

The Provider

On the other hand, the interface provider implements this interface by creating a C++ class and inheriting the interface. This way the C++ compiler will force the code to implement all the functions ... otherwise it will not compile:

class CSomeInterfaceImpl : public VCOMImpl<ISomeInterface>
{
public:
  virtual void Function()
  {
    ...
  }
};

Then the provider will create an instance when requested and return it as a VCOM interface. Also it would delete that instance when requested:

IVWUnknown* QueryInstance(VWIID iid)
{
   if ( iid == IID_SomeInterface )
       return new CSomeInterfaceImpl();
}

void ReleaseInstance(VWIID iid, IVWUnknown* instance)
{
   if ( iid == IID_SomeInterface )
      delete (CSomeInterfaceImpl*) instance;
}

SDK Extensions

The VCOM mechanism allows plug-ins to provide and use interfaces, whether the interface was provided by Vectorworks or other 3rd party plug-ins. The SDK defines specific interfaces that Vectorworks understands. The best example is the IExtension interface, and its more specialized derivatives: IExtensionMenu, IExtensionParametric, and IExtensionTool interfaces.

The above plug-in module implements three extensions. Two of the extensions, MyMenu1 and MyMenu2, are two separate implementations of the IExtensionMenu interface, and MyObject is an extension of the interface IExtensionParametric. Note that the SDK provides wrapper classes for those interfaces to simplify the implementation. We will be using these SDK classes in this tutorial.

When Vectorworks is launched, it enumerates all available extension implementations provided by each module plug-in. Then, when needed, Vectorworks will query an instance of this interface on which the plug-in will 'new' the class and return the pointer back. Vectorworks will use that instance and ask the plug-in to delete it when it is no longer needed.

Module Main

The module plug-in has a single entry point that serves three purposes:

  1. Enumerate all available interfaces provided by this module;
  2. Create instance of the requested interface;
  3. Delete an instance provided by this module that is no longer in use;

The module main of the TesterModule can be found in ModuleMain.cpp and looks like this:

extern "C" long GS_EXTERNAL_ENTRY plugin_main(long action, void* pInfo, long& ioData, CallBackPtr cbp)
{
  // initialize VCOM mechanizm
  ::GS_InitializeVCOM( cbp );

  // init legacy Global Callback Pointer
  // for support of legacy GS_ functions
  gCBP  = cbp;

  { // Init gSDK
    using namespace VectorWorks;
    VCOMPtr<ISDK>  localSDK( IID_SDK );
    gSDK  = localSDK;
  }

  long  reply  = 0L;

  using namespace VWFC::PluginSupport;

  REGISTER_Extension<TesterModule::CExtTool>( GROUPID_ExtensionTool, action, pInfo, ioData, cbp, reply );
  REGISTER_Extension<TesterModule::CExtMenu>( GROUPID_ExtensionMenu, action, pInfo, ioData, cbp, reply );
  REGISTER_Extension<TesterModule::CExtObj>( GROUPID_ExtensionParametric, action, pInfo, ioData, cbp, reply );
  REGISTER_Extension<TesterModule::CExtVSFuncs>( GROUPID_ExtensionVSFunctions, action, pInfo, ioData, cbp, reply );
  REGISTER_Extension<TesterModule::CExtMenuDyn>( GROUPID_ExtensionMenu, action, pInfo, ioData, cbp, reply );

  return reply;
}

This function is pretty much the same for every module except for the last part where it handles different VCOM interfaces provided by this module. The first part is standard initialization of the context of this module.

The most important part in this function is the three purposes stated above. They are implemented by a single call to the template function REGISTER_Extension which manages an extension implementation. The template parameter defines the class which implements the extension, and the first parameter is the group in which this extension will be registered.

Next Chapter

Next: An Extension Implementation