Next Previous Contents

6.3 Connecting method and stub

The stub action generated for a method must somehow hook into the Haskell action that implements it. For IntRef, the component proxy code in IntRefProxy takes care of this:

module IntRefProxy where

import qualified IntRef
   (
     State
   , set     -- :: State -> Int32 -> IO ()
   , get     -- :: State -> IO Int32
   )
import qualified IIntRefProxy
import Com

foreign export stdcall "set" set :: Pointer Interface -> Int32 -> IO HRESULT
set :: Pointer Interface -> Int32 -> IO HRESULT
set = IIntRefProxy.set (IntRef.set :: IntRef.State -> Int32 -> IO ())

foreign export stdcall "get" get :: Pointer Interface -> Pointer Int32 -> IO HRESULT
get :: Pointer Interface -> Pointer Int32 -> IO HRESULT
get = IIntRefProxy.get (IntRef.get :: IntRef.State -> IO Int32)

foreign export stdcall "new" new :: Pointer GUID -> Pointer (Pointer Interface) -> IO HRESULT
new :: Pointer GUID -> Pointer (Pointer Interface) -> IO HRESULT
new piid ppvObject = ...

The component instance constructor, new, is responsible for creating the binary COM representation of the component at a particular interface, and details of how it is implemented is discussed in the next section.

The interface methods simply invoke the interface stubs in IIntRefProxy, passing the corresponding method implementation as the first argument:

module IIntRefProxy where
import ComPrim

iidIIntRef :: GUID
iidIIntRef = mkGUID "{C1DF9B10-BDDB-11d1-99CC-006097B7314A}"

set :: (a -> Int32 -> IO ()) -> Pointer Interface -> Int32 -> IO ()
set method_set iptr v = (do
   st  <- getIfaceState iptr
   method_set st v
   return s_OK)
    `catch` handleCOMError
   
get :: (a -> IO Int32) -> Pointer Interface -> Pointer Int32 -> IO ()
get method_get iptr ptr = (do
   st  <- getIfaceState iptr
   v   <- method_get st
   marshallInt32At ptr v
   return s_OK)
     `catch` handleCOMError

Since each component method takes their state as the first argument, the interface stubs is responsible for fishing it out. The component state is accessible via the interface pointer, using getIfaceState:

getIfaceState :: Pointer Interface -> IO a

The getIfaceState action is provided by H/Direct, and returns the state associated with an interface pointer (see later section for details of how it is implemented). It is the responsibility of user's of IIntRefProxy to ensure that the interface state returned from getIfaceState is of the type expected by the method action.

The interface stubs are responsible for marshaling arguments and results to and from the representation expected by the Haskell method, but in the case of IIntRef's methods, there's little marshaling to be done.


Next Previous Contents