Files

RobotGuid.h
Contains all GUIDs for classes and interfaces
RobotLib.h
Main include file for using the object library.
Helper.h
Helper functions for setting up registry entries and maintaining object/lock counts
StrCast.h
Macros for string type conversions

Quick Start

The sample folder contains a sample Visual C++ project for building a new module. The files have been annotated to simplify the process of customizing the code. Simply search for TODO: and make the necessary changes as indicated.

Basics

The kernel provides a middle layer through which the user interface, add-on modules, and the robot can talk to each other. The user interface creates an instance of the kernel, through which it requests modules to be loaded. There are two interfaces that you will have to deal with. The kernel implements the IRobot interface. Each module implements the IRbtModule interface. In addition, modules may implement interfaces specific to the type of functionality they provide. As long as two modules implement the same set of interfaces, they can be exchanged for one another. For example, you can write a module that implements the IRbtBaseAV interface to replace the default video module. In addition to implementing the IRbtModule interface, each module must write a certain number of registry entries in order for the kernel to find the module. These include the standard set of entries needed by the COM runtime to find the DLL in which the object resides. For details, please refer to the Platform SDK documentation. You can also use the helper functions RbtRegisterObject/RbtUnregisterObject defined in Helper.h to setup these entries. You will also need to add an entry under HKLM\Pacific Star\Robot Modules. This entry allows the kernel to enumerate the modules present in a system. The name of the value should be the name of the module, and the value should be the CLSID of the class. You can use the helper functions RbtRegisterModule/RbtUnregisterModule to add such entries.

Startup/Shutdown

The application requests that a module be loaded by calling the AddModule function on the kernel. The kernel uses the provided CLSID to create an instance of the module object. If successful, the kernel will then attempt to retrieve a pointer to the IRbtModule interface of the module. Finally, the kernel calls Init on the module object, passing in a reference to itself. During initialization, your module can call FindInterface and GetModule on the kernel to obtain pointers to other modules on which it depends. FindInterface fails with E_NOINTERFACE if none of the currently loaded modules export the requested interface. You can then determine whether to load another module or to fail. If Init fails, the kernel calls Unload on the module, destroys the object, and returns E_FAIL to the application. The application can request that a module be unloaded by calling RemoveModule. The kernel will then call Unload on the module and destroy the object.

Custom Actions

Modules can have actions that are directly invoked by the user. To support this, modules should implement the ISpecifyActions interface. The application can then enumerate through the modules, attempting to obtain the ISpecifyActions interface on each module. For those that implement the interface, GetActions will be called to obtain a list of actions that can be invoked. When an action is invoked, the Dispatch function is called with the name of the action.

Events

Modules should register their events by calling RegisterEvent on the kernel. This returns one or two EventID's, depending on whether the event is a simple event or an event/anti-event pair. You can then trigger an event by calling FireEvent, providing the EventID obtained from RegisterEvent. When a module unloads, it should remove its events by calling UnregisterEvent. Note that removing an event also removes its associated anti-event. When an event is added, the kernel fires the Base.NewEvent event. Similarly, when an event is removed, the kernel fires the Base.RemoveEvent event. To listen to events, the module should implement these steps:
  1. Implement the IRbtCustomSink and/or the IRbtEventSink interfaces.
  2. Obtain the IConnectionPointContainer interface of the kernel
  3. Use FindConnectionPoint on the interface to find the needed connection point. There are two connection points: IID_IRbtCustomSink and IID_IRbtEventSink. Events created by modules are routed through the first, while kernel events (add/remove module, add/remove event) are routed through the second
  4. Call Advise on the connection point, passing in a pointer to your implementation of IRbtCustomSink/IRbtEventSink. Save the cookie that is returned
  5. Release interface pointers
Once these steps have been performed, the module is hooked up to receive event notifications. Every time an event fires, the appropriate function on your implementation of the IRbtCustomSink or IRbtEventSink interface is called. On unload, the module should disconnect its connection points by obtaining the IConnectionPoint pointers and calling Unadvise with the cookies returned by Advise.