Different behaviour passing array to COM object from WebService and standalone C#

M

Marco

Hello there,

We're new to C# and have noticed a strange behaviour which we don't
yet understand.

We wrote a COM DLL (in VC++ 6.0) which performs some calculation based
on some double arrays passed as input parameters to the DLL through
the SetParams method defined as follows:

interface ICliquet : IPricable
{

HRESULT SetParams([in]long double year_min, long double
monthly_floor,
long double monthly_cap, long double *
drift,
long double * volatility, long double *
dividend,
long double * timespan, long periods,
long double firstmonthquote, long double
rel);
};

(IPricable implements IDispatch)

We can properly add a reference to the COM object through the interop
by VStudio .NET which declares the double* as float64&.

The method works fine when used in a standalone C# application
(declaring the input arrays as...

double [] volatility = new double[1000];

....calls the COM method by...

obj.SetParams(...., ref volatility[0], ...)

The problem arises when doing the same in a C# WebService since the
double arrays are "cleared" (seem to be "zeroed") when passed to the
COM object!

No error is returned (the COM object works "fine" on zeroed input
data!).

It looks like a marshalling problem... the interop assemplies look the
same for both the WS and the standalone solution.

Any hitns?

Thank you!!!

-- Marco & Marcello --
 
B

Benne

I can't help you with the C++ part, but i can tell you, that when i use
WebServices and returning ArrayLists or something, then it gets converted to
object[]. So i would try to pass objects (System.Object) back and forth, and
typecast it in the C++ code, and in the WebService.

:) Bene
 
N

Nicholas Paldino [.NET/C# MVP]

Marco,

The declaration that is being created is incorrect. The reason for this
is that the declaration doesn't indicate to the runtime how to correctly
marshal the arrays of doubles.

You will have to declare the COM interface on your own. For the method
that takes double arrays, you will want to do the following:

void SetParams(double year_min, double monthly_floor, double monthly_cap,
[MarshalAs(UnmanagedType.LPArray)]
double[] drift,
[MarshalAs(UnmanagedType.LPArray)]
double[] volatility,
[MarshalAs(UnmanagedType.LPArray)]
double[] dividend,
[MarshalAs(UnmanagedType.LPArray)]
double[] timespan,
int periods,
double firstmonthquote,
double rel);

If the method modifies any of the values, then you will have to use
unsafe code to make the call (to pin the array addresses) or you will have
to marshal the arrays by yourself.

It should be noted that your interface is not a true automation
interface, and should not be derived from IDispatch. Arrays on automation
interfaces are of type SAFEARRAY.

Hope this helps.
 
M

Marco Ganz

Nicholas and co.,

Thank you indeed for your useful answers! I reverted to "clean"
automation and used SAFEARRAY to pass my arrays over to (and back
from) the DLL from the C# WebService as well as the standalone app!

Being new to this stuff I found Nichola's explanation about the
marshaller very interesting ineed: I'm going to try your suggestion
asap!

Thank you again and just drop me a message should you pass by Rome:
you deserve a beer!

-- Marco --
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top