Re: Using same interfaces for in-proc vs. out-proc
Drew <dam@dam.com> wrote:
At run-time, COM machinery itself uses the type library to allow COM
calls to work across apartment (e.g. process) boundaries: this is
known as "marshalling". That's why an interface IID needs to point to
a LIBID in the registry. Also, ATL's IDispatchImpl happens to use a
type library to forward late-bound IDispatch::Invoke calls to
appropriate interface methods, and also needs the type library
registered so that it can look it up by LIBID. Note that this is an
implementation detail of your server, not a requirement imposed by
the client.
------------
That sounds like a bit of a contradiction to your statement that a
reference to a server is not looked up using the LIBID. IOW, "...an
interface IID needs to point to a LIBID in the registry. Also, ATL's
IDispatchImpl happens to use a type library to forward late-bound
IDispatch::Invoke calls to appropriate interface methods, and also
needs the type library registered so that it can look it up by LIBID.
In both cases, the type library is needed to get the definition of an =
interface, not a "server" (whatever you mean by that term). Multiple =
"servers" (coclasses) may implement the same interface.
" When I create a VBA script that wants to use my COM server, I
select from a list of registered servers that are described using the
helpstring (if there is one) that appears at the library block scope.
Yes, that's what the coclass statement is for - basically, just a =
convenience for certain clients.
------------
Now, often but not always, a type library contains one or more
"coclass" blocks mentioning specific CLSIDs. This is done mostly for
the benefit of clients like VBA that consult type libraries during
compilation: these CLSID references are not used at runtime in any
way.
In your situation, with two coclasses sharing a set of interfaces, I
can suggest two approaches. One is a single type library with two
coclass blocks:
library {
[dual]
interface IMySharedInterface : IDispatch {...};
coclass MyInProcServer {
[default] interface IMySharedInterface;
};
coclass MyOutOfProcServer {
[default] interface IMySharedInterface;
};
}
The other involves three IDL files compiled into three type libraries:
// shared.idl
library {
[dual]
interface IMySharedInterface : IDispatch {...};
}
// inproc.idl
library {
importlib("shared.tlb")
coclass MyInProcServer {
[default] interface IMySharedInterface;
};
}
// outpfproc.idl
library {
importlib("shared.tlb")
coclass MyOutOfProcServer {
[default] interface IMySharedInterface;
};
}
The single type library in the first case, and the shared type
library in the second, would be packaged as a standalone TLB file and
treated as a shared resource for deployment purposes (that is, it
should be installed and registered as long as at least one of your
servers is still present on the machine). The two coclass-specific
type libraries in the second approach could go into their
corresponding servers' resources.
---------------
Both of these approaches, I assume, would use a non-unique GUID for
LIBID, and unique GUIDs, at the very least, for each coclass.
I'm not sure I understand this statement. Each of the .idl files shown =
above would have its own unique LIBID. So you would have one LIBID with =
the first apporach, and three distinct LIBIDs with the second. And, of =
course, a unique CLSID for each coclass.
The IID
for each interface looks like it is the only thing, and possibly
GUIDs for UDTs that can remain non-unique.
With both approaches, the interface (and the UDT's, whatever) is defined =
only once, so naturally there's only one IID for it. That's the whole =
point of the exercise.
If that's the case then
our present situation where all GUIDs are different between DLL and
EXE isn't much different than what you are proposing but puts more of
an onus on the client in that when they write code like:
Dim MyApp as MyLibrary.MyInProcServer
currently they can switch to using the DLL version just by changing
the reference to point to the DLL version and doing:
Dim MyApp as MyLibraryX.MyInProcServer
With your solution they would have to do:
Dim MyApp as MyLibrary.MyInProcServer
and to switch to using the DLL they would have to change their code
to:
Dim MyApp as MyLibrary.MyOutOfProcServer
Is that correct?
For references to coclasses, yes. However, references to interfaces, =
UDTs and so on won't require any changes. And, you'll have a sane =
deployment story.
--
With best wishes,
Igor Tandetnik
With sufficient thrust, pigs fly just fine. However, this is not =
necessarily a good idea. It is hard to be sure where they are going to =
land, and it could be dangerous sitting under them as they fly overhead. =
-- RFC 1925