Flylib.com

Books Software

 
 
 

Support for Scripting


Support for Scripting

Any time you run the ATL Simple Object Wizard and choose Dual as the interface type, ATL generates an interface definition for the default interface that derives from IDispatch and is marked with the dual attribute, and places it in the IDL file. Because it derives from IDispatch , our dual interface can be used by scripting clients such as Active Server Pages (ASP), Internet Explorer (IE), and Windows Script Host (WSH). When our COM class supports IDispatch , we can use objects of that class from scripting environments. Here's an example HTML page that uses an instance of the CalcPi object:

<object classid="clsid:859512CF-E4D8-450C-AF09-6578FE2F6DC2"
        id=objPiCalculator>
</object>

<script language=vbscript>
  ' Set the digits property
  objPiCalculator.digits = 5

  ' Calculate pi
  dim pi
  pi = objPiCalculator.CalcPi

  ' Tell the world!
  document.write "Pi to " &

objPiCalculator.digits

& _
    " digits is " & pi
</script>


For more information about how to handle the inconvenient data types associated with scriptingnamely, BSTR s and VARIANT ssee Chapter 2, "Text and Strings," and Chapter 3, "ATL Smart Types."



Adding Persistence

ATL provides base classes for objects that want to be persistentthat is, saved to some persistence medium (such as a disk) and restored later. COM objects expose this support by implementing one of the COM persistence interfaces, such as IPersistStreamInit , IPersistStorage , or IPersistPropertyBag . ATL provides implementation of these three persistence interfacesnamely, IPersistStreamInitImpl , IPersistStorageImpl , and IPersistPropertyBagImpl . Your COM object supports persistence by deriving from any of these base classes, adding the interface to your COM_MAP , and adding a data member called m_bRequiresSave that each of these base classes expects.

class ATL_NO_VTABLE CCalcPi :
  public ICalcPi,
  public IAdvertiseMyself,

public IPersistPropertyBagImpl<CCalcPi>

{
public:
  ...

  // ICalcPi
public:
  STDMETHOD(CalcPi)(/*[out, retval]*/ BSTR* pbstrPi);
  STDMETHOD(get_Digits)(/*[out, retval]*/ long *pVal);
  STDMETHOD(put_Digits)(/*[in]*/ long newVal);

public:

BOOL m_bRequiresSave; // Used by persistence base classes

private:
  long m_nDigits;
};


However, that's not quite all there is to it. ATL's implementation of persistence needs to know which parts of your object need to be saved and restored. For that information, ATL's implementations of the persistent interfaces rely on a table of object properties that you want to persist between sessions. This table, called a PROP_MAP , contains a mapping of property names and dispatch identifiers (as defined in the IDL file). So, given the following interface:

[
object,
...
]
interface ICalcPi : IDispatch {
    [propget, id(1)] HRESULT Digits([out, retval] LONG* pVal);
    [propput, id(1)] HRESULT Digits([in] LONG newVal);
};


the PROP_MAP would be contained inside our implementation of ICalcPi like this:

class ATL_NO_VTABLE CCalcPi : ...
{
  ...
public:

BEGIN_PROP_MAP(CCalcPi)


PROP_ENTRY(

"

Digits

"

, 1, CLSID_NULL)


END_PROP_MAP()

};


Given an implementation of IPersistPropertyBag , our IE sample code can be expanded to support initialization of object properties via persistence using the <param> tag:

<object classid="clsid:E5F91723-E7AD-4596-AC90-17586D400BF7"
        id=objPiCalculator>

<param name=digits value=5>

</object>

<script language=vbscript>
  ' Calculate pi
  dim pi
  pi = objPiCalculator.CalcPi

  ' Tell the world!
  document.write "Pi to " & objPiCalculator.digits &_
    " digits is " & pi
</script>


For more information about ATL's implementation of persistence, see Chapter 7, "Persistence in ATL."