COM/CORBA/DCOP (was: Hello people. I have some questions)
Neil Hodgson
nhodgson at bigpond.net.au
Mon Sep 10 19:39:46 EDT 2001
Alex Martelli:
> Visual Basic, no doubt the most widely deployed implementation of COM,
> seems to do fine in this regard (despite having quite a few bugs of its
> own). Re books, I don't have it at hand to check, but I think Don Box's
> excellent books (Essential COM and Effective COM, the latter with many
> co-authors) may address the issue.
Here is some code from "Essential COM" (page 388 but there is similar code
throughout the book):
STDMETHODIMP QueryInterface(REFIID riid, void**ppv) {
if (riid == IID_IUnknown)
*ppv = static_cast<IUnknown*>(this);
//...
This will crash if given a bad ppv pointer.
Not much about exceptions although around page 88 is a discussion on
SetErrorInfo.
> > The only explanation I can find for "restricted" is that it is not
for
> > use by macro programmers or end users.
>
> That's the design-intent, yes. Stopping the name->dispid translation step
> is one good way to implement that design-intent, and it's exactly how the
> system-provided API's implement it. Make a toy ATL project called resem
> with just one COM object in it, with an interface (sorry if I don't copy
> and paste, but I'm composing this response on a Linux box and the Win box
> next to it isn't networked right now):
>
> [object, uuid(...), dual, etc etc]
> interface IPeep: IDispatch
> {
> [id(1)] HRESULT Avail();
> [id(2), restricted] HRESULT Restr();
> }
>
> and here's the result when you use it from Python:
>
> >>> pp=win32com.client.Dispatch('resem.Peep')
> >>> pp.Avail()
> >>> pp.Restr()
> gets error HRESULT -2147352573, aka 0x80020003, aka
> DISP_E_MEMBERNOTFOUND
But that isn't the result from calling GetIDsOfNames. If you try this
code (with appropriate adjustment for whatever names you are using):
// COM blowup demonstration program
#include <stdio.h>
#include "Windows.h"
int main(int, char *[]) {
// Want to see the trace before crashing
setvbuf(stdout, 0, _IONBF, 0);
printf("Starting demo\n");
HRESULT hr =S_OK;
hr = ::CoInitialize(0);
if (FAILED(hr)) {
printf("Failed CoInitialize %x\n", hr);
return 1;
}
CLSID clsid;
hr = ::CLSIDFromProgID(L"Resem.rs.1", &clsid);
if (FAILED(hr)) {
printf("Failed CLSIDFromProgID %x\n", hr);
return 1;
}
IDispatch *pdisp = 0;
hr = ::CoCreateInstance(clsid, 0,
CLSCTX_INPROC_SERVER,
IID_IDispatch, (void**)&pdisp);
if (FAILED(hr)) {
printf("Failed CoCreateInstance %x\n", hr);
return 1;
}
DISPID did = 0;
OLECHAR *name = L"Restr";
hr = pdisp->GetIDsOfNames(IID_NULL, &name, 1, LOCALE_SYSTEM_DEFAULT,
&did);
if (FAILED(hr)) {
printf("Failed GetIDsOfNames %x\n", hr);
return 1;
} else {
printf("Succeeded GetIDsOfNames dispid = %d\n", did);
}
}
You will see:
Succeeded GetIDsOfNames dispid = 2
It is likely that Python's code is looking at the TypeInfo so it can do
the right thing as a 'macro programming' high level language.
> > So you are prepared to not follow the letter of the specification for
> > the
> > dispatch identifier? (Of course I can argue both sides :-) )
>
> Absolutely not! Where are you reading this?!
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/automat/htm
_hh2/chap5_61id.asp
"""dispIdMember
Identifies the member. Use GetIDsOfNames or the object's documentation to
obtain the dispatch identifier. """
Neil
More information about the Python-list
mailing list