HOWTO: Marshall a string from VB6 to C#

S

Simon Woods

Hi

I am using COM Interop. I have a call in VB6 which returns a string of
roughly 13000 chars. If I execute the call in pure VB6 it takes about
800ms to execute. If I execute it via c# and COM Interop it takes about
8 seconds. I'm assuming the delay is caused by marshaling.

If I am correct about marshaling, I'd be grateful if someone could
suggest the fastest way I can get this into C#. e.g. Would it be better
to, say
a) expose it as a byte array
b) provide a byref string param into the VB6 layer

I would appreciate some sample code as well. I tried the

Marshal.PtrToStringAuto(
Marshal.ReadIntPtr(myCOMObject.GetString(myParam), 0
)

to no avail.

--

I am simply referencing the VB6 dll (so it is "in process") from a C#
dll. Here's an extract from OLEView

interface _MyCOMObect : IDispatch {
...
[id(0x60030006)]
HRESULT GetString(
[in] _IEventHistory* p_oEventHistory,
[out, retval] _IXML** );
...
};

[
uuid(09A06762-5322-4DC1-90DD-321D4EFC9C3E),
version(1.0),
custom({17093CC6-9BD2-11CF-AA4F-304BF89C0001}, "0")
]
coclass MyCOMObject {
[default] interface _CFactory;
};

[
odl,
uuid(C6E7413F-C63A-43E4-8B67-6AEAD132F5E5),
version(1.0),
hidden,
dual,
nonextensible,
oleautomation
]

I should probably point out that the parameter (p_oEventHistory) is
another COM object which I am instantiating in C# but that takes about
80ms. I have tried removing this, as well as the return type, so that I
was simply passing and receive strings rather than a more complex COM
interface and this indeed reduced the execution time by 1 second. But it
still meant that it is taking about 7 secs to marshall 13000 chars -
which seems excessive, tmm. But perhaps not?

Any thoughts would be gratefully received

Thx

Simon
 
S

Simon Woods

As I've looked into it more, I probably should have mentioned that the
VB6 dll resides in COM+. When I step the code, the delay certainly
occurs after I leave VB6 and before I return to C#, so I'm wondering if
COM+ is potentially a culprit ... though I'm not sure how best to
diagnose this.
 
P

Peter Duniho

Simon said:
Hi

I am using COM Interop. I have a call in VB6 which returns a string of
roughly 13000 chars. If I execute the call in pure VB6 it takes about
800ms to execute. If I execute it via c# and COM Interop it takes about
8 seconds. I'm assuming the delay is caused by marshaling. [...]

It very well might be that's the cause. But if so, IMHO that's a bug.

If you were building the string up one character at a time over a COM
interop marshaling layer, _then_ perhaps 8 seconds could be justified.
But to copy the string as a single operation should be very fast.

I agree with your assessment that 8 seconds is an unreasonably long
amount of time.

Though, that said, while I don't know much about VB6 (in particular, are
you executing your code as compiled native, or is there a VB6
interpreter executing it?), 800 ms also sounds excessively long. Both
of those timings sounds reasonable for a computer build in the mid- to
late-90's, not modern hardware.

Unfortunately, without a concise-but-complete code example that reliably
reproduces the problem, it's not going to be easy to identify a specific
problem. You should try to provide such an example if you want detailed
help with the problem.

Pete
 
S

Simon Woods

Simon said:
Hi

I am using COM Interop. I have a call in VB6 which returns a string of
roughly 13000 chars. If I execute the call in pure VB6 it takes about
800ms to execute. If I execute it via c# and COM Interop it takes
about 8 seconds. I'm assuming the delay is caused by marshaling. [...]

It very well might be that's the cause. But if so, IMHO that's a bug.

If you were building the string up one character at a time over a COM
interop marshaling layer, _then_ perhaps 8 seconds could be justified.
But to copy the string as a single operation should be very fast.

I agree with your assessment that 8 seconds is an unreasonably long
amount of time.

Though, that said, while I don't know much about VB6 (in particular, are
you executing your code as compiled native, or is there a VB6
interpreter executing it?), 800 ms also sounds excessively long. Both of
those timings sounds reasonable for a computer build in the mid- to
late-90's, not modern hardware.

FYI ... it turned out that if I restructured and modified one of the
objects being instantiated via COM+ to use only simple data types rather
than, as I was doing, using (and caching) more complex types, the speed
improved to about 400ms.

Having said that, I'm not quite sure why that sorted things out.

Thx for your input. It was in trying to create a but
concise-but-complete example that lead me to this as a way forward.

S
 
P

Peter Duniho

Simon said:
FYI ... it turned out that if I restructured and modified one of the
objects being instantiated via COM+ to use only simple data types rather
than, as I was doing, using (and caching) more complex types, the speed
improved to about 400ms.

Having said that, I'm not quite sure why that sorted things out.

Thx for your input. It was in trying to create a but
concise-but-complete example that lead me to this as a way forward.

It often does. That's one of the reasons it's so important to make one. :)

As for the specific issue, while your original question seemed to imply
that you were simply passing a string, it sounds as though your function
call actually involved a far more complex data type. If so, then
changing the data type can definitely affect the behavior. In
particular, .NET p/invoke and COM marshaling will look at the type and
do different kinds of marshaling depending on the layout and exact
contents of the type.

And in particular, there's a big performance difference between
"blittable" and "non-blittable" types. With the former, the marshaler
will just pass a pointer to the pinned object, while as with the latter,
the marshaler has to copy each individual member of the type.

I still don't think that 8 seconds is a reasonable amount of time for a
single function call, not on any computer that can run .NET. But I
suppose if you had a particularly complex data structure, it might be
possible to get into some worst-case scenario where that happened.

Pete
 

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