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:
- Implement the IRbtCustomSink and/or the IRbtEventSink
interfaces.
- Obtain the IConnectionPointContainer interface of the kernel
- 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
- Call Advise on the connection point, passing in a pointer to your
implementation of IRbtCustomSink/IRbtEventSink. Save the cookie
that is returned
- 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.