Since one of HaskellDirect's goals is to support the integration of Haskell with COM, it has got some options specific for the COM backend:
-fno-gen-binary-interface
When generating stubs that has to work with HaskellScript, non-Automation interfaces are not of interest, due to the fact that they currently cannot be handled directly. This option causes the compiler to ignore such interfaces, emitting just a message informing the user what's happened.
This option is of less use now that HDirect is capable of generating Hugs stubs to binary interfaces.
-fuse-dispids
For Automation compatible interfaces, method invocation is either
done by referring to the method by name (the default) or by method id
(specified using the id() attribute.) Going via method ids
(or, dispids, using Automation lingo) is quicker as it saves
performing the method name to identifier mapping each time the
method is invoked. If you want to do this, -fuse-dispids
is your friend.
-fkeep-hresult
Methods of a COM interface return an HRESULT to
indicate the success or otherwise of the method invocation.
The HaskellDirect generated stubs will by default look at
this status code to determine whether to flag an exception or not.
To disable this inspection of the HRESULT an instead
have it returned back along with the other results of the method,
use -fkeep-hresult.
-fcoalesce-methods
When working with Automation interfaces, you'll sometimes find that
methods of different interfaces have the same name and take
the same list of parameters (modulo the interface pointer, of
course.) The -fcoalesce-methods option combines together
the stubs for isomorphic methods into one. For example,
[...]
interface IA : IDispatch {
HRESULT lookup([in,string]BSTR name, [out]int* res);
...
};
[...]
interface IB : IDispatch {
HRESULT lookup([in,string]BSTR name, [out]int* res);
...
};
With -fcoalesce-methods enabled, only one lookup
stub will be generated:
lookup :: Int -> IDispatch a -> IO Int
Notice that this isn't entirely typesafe, since lookup can
now be applied to any IDispatch interface pointer, not
just IA and IB ones. If you do, a Haskell IO
exception will be raised, telling you that method lookup
isn't supported by that particular object.
In some cases, this trade-off between type safety and size of the generated stub code is worth considering, since method coalescion can drastically reduce the amount of stubs you need to generate for particular components / object models.
-fsubtyped-interface-pointers
This option is now enabled by default, so you really shouldn't have to use it any longer. It causes interface pointers to be represented in Haskell in a way that allows us to easily reuse the method stubs of the interface(s) we're inheriting from. To demonstrate, suppose you have the following two interfaces:
[...]
interface IPlus : IUnknown {
HRESULT add([in]int i1, [in]int i2,[out]int* res);
};
[...]
interface IPlusMinus : IPlus {
HRESULT sub([in]int i1, [in]int i2,[out]int* res);
};
i.e., you can perform the add operation on an instance of the
IPlus interface, while instances of IPlusMinus also
allow you to perform the sub operation. Having to generate
one add stub for IPlus and IPlusMinus would
be tedious in the extreme, so let's avoid this by representing
the interface pointers themselves as follows:
type IPlusMinus a = IPlus (PlusMinus a)
data IPlusMinus_ a = IPlusMinus_
type IPlus a = IUnknown (Plus a)
data IPlus_ a = IPlus_
A value of type IPlus is a COM interface pointer that, at
least, supports the methods of the IPlus interface.
The IPlusMinus interface is of IPlus's ilk, being
defined as a synonym for IPlus. Expanding out the
type synonyms is illuminating:
type IPlusMinus a = IPlus (IPlusMinus_ a)
= IUnknown (IPlus_ (IPlusMinus_ a))
i.e., by parameterising the interface pointers over a type that
describes the extension of the interface, the relationship between
IPlus and IPlusMinus interfaces is maintained at the
Haskell type level, with IUnknown's type parameter envoding
the interface inheritance chain.
The dummy types Plus and PlusMinus are needed to let
the type checker do it's job of catching illegal uses of interface
pointers, e.g., the application of sub to an interface
pointer that just implements IPlus.
Since IPlusMinus is a synonym for IPlus, the
generated stub for add can now also be used by
IPlusMinus:
add :: Int -> Int -> IPlus a -> IO Int
sub :: Int -> Int -> IPlusMinus a -> IO Int
-funparamed-interface-pointers
Use a representation of interface types that isn't parameterised over the sub type, but a mere type synonym to the interface type it inherits from, e.g.,
type IPlus = IUnknown
type IPlusMinus = IPlus
-fignore-dispinterfacesFor a COM component that support more than one IUnknown interface,
there's a problem when it comes to providing an Automation interface
to the same functionality, since supporting multiple
IDispatch interfaces is tricky.
One solution to the problem is to define one big 'dispinterface' containing all the methods of the various binary COM interfaces. Not particularly pretty, but that's how several IDL specs solve this problem.
When generating client bindings, you're not really interested
in both the IDispatch interface to a method and the
'binary' one. In case it's the latter, -fignore-dispinterfaces
causes the compiler to simply overlook dispinterfaces when
generating stubs. Sometimes useful.
The -fignore-dispinterfaces option is the inverse of
-fno-gen-binary-interface option.
-fsort-defns
The compiler currently makes the assumption that the definition of an IDL entity preceedes any of its uses (as does MIDL and other IDL compilers). So, if you feed it input where this isn't the case, use -fsort-defns to dependency sort the declarations before processing them further.
With a little bit of work this assumption could be dropped, but until
that time, -fsort-defns is your friend.
Note: if you're feeding HaskellDirect input you got through the use of
Microsoft's OleView utility, -fsort-defns is required, as
that tool does not sort the IDL it generates. To avoid such troubles
alltogether, simply avoid OleView and have HaskellDirect process the type
libraries for you directly.
-fdual-vtbl
Dual interfaces can either be invoked via the vtbl (i.e., 'binary'
invocation) or through IDispatch and Invoke().
The option -fdual-vtbl instructs the compiler to generate
stubs that perform method invocation via the vtbl (the default
is the other way around.)
-fno-expand-inherited
For interfaces that inherit from a non-'builtin' interface (i.e.,
IUnknown and IDispatch), don't expand the
contents of the inherited interface when compiling the
interface that inherits. Experimental, not really of use with
the current interface pointer representation.
-fprefix-interface-name
Prepend the name of the interface to the names of the Haskell method
stubs. This is one way to fight namespace clashes, the default scheme
used is to make method names unique within one Haskell module by
appending a unique number to methods with the same (Haskell) name,
i.e., if there's two methods called next, the second will be
renamed to next0. -fprefix-interface-name offers an
alternative to this scheme, mapping next0 to iEnumFoo_Next
instead.
-fno-overload-variant
By default, argument occurrences of the Automation VARIANT
type will cause HaskellDirect to overload the corresponding Haskell
method argument using the Automation.Variant type class.
To turn this behaviour off, use -fno-overload-variant to
have VARIANT map to Automation.VARIANT instead;
a pointer to an externally-allocated VARIANT value.
-fno-enum-magic
The COM specification specifies the assumed `shape' of enumeration interfaces, i.e., interfaces that lets you enumerate the elements present in a collection. The only difference between two enumeration interfaces is the type of elements that they allows the client to enumerate over. So, providing a shared set of stubs for these enumeration methods makes good sense, parameterising the stubs on how to unpack the enumeration values the interface methods return.
HaskellDirect will by default generate code that makes use of these
parameterised enumeration stubs, but should you for one reason or
another not want to use these, use -fno-enum-magic to turn
this default off.
-fno-mangle-interface-names
Turn off interface name mangling for interface dummy types. Experimental and not a particularly useful option.
--tlb
HaskellDirect supports the reading of type libraries on Win32
platforms. Use --tlb to try to open the input files
on the command line as type libraries.
-ftreat-importlibs-as-imports
A deprecated option, which instead of trying to import type
information from a type library when it encounters a
importlib() statement, will try to import from the
corresponding IDL (source) file instead.
This option was of some use before HaskellDirect supported the reading of type libraries - of little use now.
-fanon-typelib
For Haskell COM components that implement the interface
IDispatch, the compiler will generate a type library to aid
in its implementation. This type library is normally accessed by
looking up its registered GUID, but in the event you don't want
to have the type library be registered, use -fanon-typelib.
-fmaybe-optional-params
For Automation clients, the compiler's default behaviour when encountering optional arguments is to use overloading. For example,
[...]
interface IA : IDispatch {
HRESULT meth([in,optional]int i);
};
gives
meth :: Variant a => a0 -> IA a -> IO ()
the option -fmaybe-optional-params uses a Maybe
instead, giving you
meth :: Maybe Int -> IA a -> IO ()
-fignore-importlibs
If any importlib() declarations are encountered in the IDL
input, just ignore them.
-fignore-methods-upto=Name
Instead of factoring them out, some (generated) IDL input may prefix all interfaces with a set of identical methods, i.e., the interfaces contain:
interface IA : IUnknown { HRESULT m1 (); .... }
interface IB : IUnknown { HRESULT m1 (); .... }
rather than
interface IBase : IUnknown { HRESULT m1 (); }
interface IA : IBase { HRESULT m1 (); .... }
interface IB : IBase { HRESULT m1 (); .... }
To avoid generating N stubs for m1, use
-fignore-methods-upto=m1.
-fshow-idl-in-comments
Put the IDL in comments next to the Haskell code that it generated.
-fappend-interface-short-name
Within each Haskell module generated, if there's a name clash between
two method names, they're disambiguated by appending the number
1 to the second one. The -fappend-interface-short-name
option takes a different approach at disambiguating methods by
appending the upper case letters of their corresponding interface.
For example,
interface IOleFoo : IUnknown {
HRESULT meth();
};
interface IOleBar : IUnknown {
HRESULT meth();
};
The stub for the method IOleBar.meth is named methOB
in the generated Haskell code.
-fno-gen-variant-instance
For each enumeration type, the default is to generate an instance of
the Automation.Variant class it. Use
-fno-gen-variant-instance to turn this off.
-fexplicit-i-pointer
For Automation clients, the generated stubs does not give the
interface pointer explicitly as an argument. To have it do so,
use -fexplicit-i-pointer.
-fno-library-ids
For each library declaration, we generate a Haskell
definition of its LIBID. To disable this, use
-fno-library-ids.
-foverload-variant
When generating Automation client stubs, the default is to
overload arguments that have type VARIANT. To enable
this behaviour for non-Automation clients, use
-foverload-variant.
-fuse-std-dispatch
When generating proxy code for Haskell COM servers, the default is
to use the system-supplied, type library marshaller to implement
IDispatch. A simpler, Haskell-only implementation of
IDispatch is also supported by the HaskellDirect COM
libraries. To use this instead, use -fuse-std-dispatch.