[plt-scheme] MysterX and ImageMagick COM object

From: Anton van Straaten (anton at appsolutions.com)
Date: Thu Jul 24 11:00:27 EDT 2003

> > This avoids attempting a direct call through the COM function
> > pointer, when a vararg function is being invoked.
>
> I'm not sure that's necessary.

I agree that it may not be necessary to avoid using a direct call, but it
looks as though it would require quite a bit more rearranging of MysterX to
make it work this way - the type checking MysterX does on a direct call
doesn't handle vararg functions.

In addition, I'm not sure that the vararg calling convention works with a
direct call.  See below.

> As the IDL shows, there's a fixed number of arguments
> to push on the stack -- a pointer to a SAFEARRAY.

The COM 'vararg' qualifier involves a different interpretation of the IDL
signature.  A vararg function is simply a function which has zero or more
fixed arguments, followed by a variable number of arguments.  When calling a
vararg function from a higher-level language than C, the caller simply lists
all the arguments sequentially.  The actual calling convention does the same
thing: it stores all the arguments - both fixed and variable - contiguously
in the 'rgvarg' array in the DISPPARAMs structure passed to
IDispatch::Invoke.

It's only in the IDL that things look different.  The IDL signature of a
vararg function consists of zero or more fixed arguments, followed by a
SAFEARRAY of VARIANTs, followed by the return value (if any?)  This layout
apparently describes what happens inside the COM implementation.

> This approach smears the arguments into the vector of arguments
> used by IDispatch::Invoke().  Does MS say this is what to do
> SAFEARRAYs in general?

Not for SAFEARRAYs in general, only for the last SAFEARRAY in the parameter
list of a vararg function.

I dug up an MS KB on the subject:
http://support.microsoft.com/support/kb/articles/Q158/4/51.asp

The very last paragraph sheds some light on this:

"Although the type information for the MyFunc1 function specifies that a
SAFEARRAY* be passed in, a SAFEARRAY was not created [in the example] and
passed to the invoke call by the caller. The caller passes an array of
variants along with the one required parameter and the total count of all
arguments in the DISPARAMS structure. The implementation of Invoke in the
server will create a SAFEARRAY, package the passed-in array of variants into
the SAFEARRAY, and then pass the SAFEARRAY pointer to the server's method.
Therefore, the responsibility for creating the SAFEARRAY to pass to MyFunc1
does not fall on the caller. The caller needs to package all of the extra
parameters it wishes to pass in a flat array (contained in the DISPARAMS
struct) and invoke the method."

Anton



Posted on the users mailing list.