GHC and C++ (was RE: Creating COM objects and passing out pointers to them via a COM interface)

Simon Peyton-Jones simonpj@microsoft.com
Thu, 6 Feb 2003 15:02:45 -0000


| 1. A facility to replace the default uncaught exception behaviour for
COM
| objects and similar shared library code

I'm out of my depth here.  I think that if those interested in COMish
things get a consensus on what would be the Right Thing, and have some
idea about implementation, we'd be willing to help fix GHC to do the
Right Thing, if it wasn't too hard.

| 2. HDirect rolled into the main GHC tree
|=20
| 3. A facility within HDirect to create COM objects based on existing
| (Haskell) data structures, returning an interface pointer as a return
| parameter on a call to an existing COM object. (This was the question
Simon
| asked if I'd had an answer to - I've attached a copy below for
reference).

Sounds great -- but Sigbjorn is HDirect supreme so we'll have to see
what he says.

Simon



| -----Original Message-----
| From: Sarah Thompson [mailto:sarah@telergy.com]
| Sent: 04 February 2003 10:34
| To: Simon Peyton-Jones; Sigbjorn Finne
| Cc: Daan Leijen; Kevin S. Millikin; Mike Thomas;
glasgow-haskell-users@haskell.org;
| Haskell-Cafe@Haskell. Org
| Subject: Re: GHC and C++ (was RE: Creating COM objects and passing out
pointers
| to them via a COM interface)
|=20
| I'm replying to two threads at the same time and cross posting my
reply,
| because they are very relevant to each other. I'm sorry if anyone here
ends
| up seeing this more than once as a consequence.
|=20
| [s]
|=20
| ------
| > Sarah
| >
| > Did you get this problem sorted out?
|=20
| Not directly. I ended up building an 'outer' COM component in C++ that
| mapped an MSXML-like interface onto a simpler, internal COM component
that
| wraps up the Haskell code. This approach seems to work well - I might
have
| been able to build the necessary wrapper directly in Haskell using
HDirect,
| but I was becoming aware that I was probably starting to take up an
| unreasonable amount of Sigbjorn's time with increasingly detailed
questions
| and I didn't have time to figure out the necessary intricacies from
scratch.
|=20
| HDirect seems very good, but I don't think it's currently in quite as
stable
| a state as the main GHC release. The problems I had in building a
version
| that works with the current GHC are an example of this. I'm not
| complaining - it worked well in the end, but I do think it might be a
'good
| thing' to consider rolling HDirect into the main GHC release at some
point.
|=20
| The other thing that bit me was exception handling, or rather the
default
| behaviour when an uncaught exception 'falls out' and reaches the top
level
| of the runtime system. Currently, the functionality appears to be to
abort
| the current process. Whilst this is probably desirable for a typical
| application executable (be that console or GUI based), it is a problem
if it
| happens inside a COM component. My thinking is quite straightforward
on
| this. Preferred behaviour should really be for a call to a COM
component to
| fail returning an error code, rather than abort the calling process.
| 'Server-style' applications are usually expected to keep running when
minor
| faults occur, rather than terminate. HDirect/GHC's current behaviour
makes
| this difficult to achieve - I managed to successfully catch
exceptions, but
| the price was needing to use some code based on DeepSeq to force deep
strict
| evaluation for all state updates. This (seemingly) was the only way I
could
| stop exceptions from happening in the context of the automatically
generated
| COM wrapper - passing it a fully evaluated data structure was
apparently the
| only solution available. However, this does break the advantages of
laziness
| as applied to the current state of the object - it would be pretty
neat, for
| example, to be able to define a view of a database as the result of an
| expression involving relational algebra combinators, with the query
| evaluated one record at a time as the data is pulled back by the
client
| application. The need for DeepSeq forces strict evaluation, so this
benefit
| is lost. This is actually more of an issue than it might immediately
seem -
| many queries don't actually need to retrieve all of a record set
before
| useful things can be done. A particular example is updating a GUI,
where a
| list box reflects the results of a query. Lazy evaluation will allow
the
| screen to start updating more or less immediately even on a query that
| returns thousands of records - strict evaluation might incur a delay
of a
| few seconds (for a very complex query or a large database) before
updates
| can start happening.
|=20
| In an ideal world, what I'd dearly love to see would be an HDirect
option
| that allows a choice between existing functionality and having calls
return
| a failure code, or better still allowing a user-supplied handler
function to
| determine the correct course of action.
|=20
| So, to sum up my wish list:
|=20
| 1. A facility to replace the default uncaught exception behaviour for
COM
| objects and similar shared library code
|=20
| 2. HDirect rolled into the main GHC tree
|=20
| 3. A facility within HDirect to create COM objects based on existing
| (Haskell) data structures, returning an interface pointer as a return
| parameter on a call to an existing COM object. (This was the question
Simon
| asked if I'd had an answer to - I've attached a copy below for
reference).
|=20
| Sarah
|=20
| PS: I've not yet looked closely at the .NET integration in GHC yet,
but I
| can imagine myself having a very similar wish list in that case too.
|=20
| --------
| Hi again,
|=20
| A slightly harder problem this time. I want to implement something
that
| looks something like the Microsoft XML parser. This is a very COM
heavy
| contraption that provides an interface that looks to client
applications
| like a tree of COM objects that reflects the internal structure of an
XML
| document.
|=20
| The idea is, you start with the document object, make a method call
| requesting the root node, and have a COM object that wraps that node
| returned to you. You can then request the children of that node, and
their
| children and siblings, all which involves being passed back interface
| pointers to COM objects. Effectively, there is one COM object per
syntactic
| item in the XML document.
|=20
| I already have my document object working nicely. This is where the
actual
| database resides. I want to be able to spawn views of this database as
COM
| objects. When I've done this in the past (using ATL mostly, euuuugh),
I've
| used an IDL definition something like
|=20
|    HRESULT CreateView([in,string] BSTR query, [out,retval] IDbView
**);
|=20
| What's the correct way to implement the necessary Haskell code to
create the
| coclass and return a pointer to it? I fiddled around for ages, but
either
| couldn't get GHC to like the types I was using, or when I finally got
it to
| compile, I found that my test harness was being passed an invalid COM
| object. This should be simple stuff, so I'm sure someone will have
done it!
|=20
| Secondly, it is a nasty, though fairly common trick, if you know your
| objects are going to be created in the same process space, to allow
them
| some 'behind the scenes' communication. In my case, I'd like to avoid
| needing to serialise and deserialise the data in a view during
creation of
| these child objects (of which there may be a great many, and which may
be
| created on the fly rather often). Ideally, I'd like to be able to do
| something like:
|=20
| newView :: String -> State -> IO State
| newView db (State st) =3D do
|     db <- readIORef st
|     r <- newIORef db
|     -- Insert some kind of COM magic here
|     return (State r)
|=20
| so the database content gets copied within the Haskell environment
(lazily,
| I'd hope), without needing to be serialised and deserialised. Is this
| feasible? One (messy) approach might be to create a bunch of extra
| interfaces on the main database object, then create 'thin wrapper'
child
| objects that simply make calls back into the parent object. I'm not so
keen
| on that for various reasons, however.
|=20
| Sarah