.NETGURU
Passing C# strings by reference to a COM object
Messages   Related Types
This message was discovered on ASPFriends.com 'aspngcs' list.


Michael Wells

I am in the process of wrapping a legacy COM object in C# classes to
simplify integration with .NET. One of the methods on the object
requires three strings to be passed by reference, so that data can be
returned.

The call is of the form...

oCOMThingy.AuthorizeEx (ref object vrt1);

According to the docs, the call was designed so that it would work with
VB Script variants, when passed by reference. Since I'm new to C#, I'm
not certain how to approach this properly. (but, some of the cobwebs
are slowly falling away from my C++ experience)=20

[ ATTEMPT #1 ]
An "unannotated" call, such as...

string sz;
oCOMThingy.AuthorizeEx (sz);

...errors as "cannot convert from string to 'ref object'"

[ ATTEMPT #2 ]
Casting the param, as in...=20

string sz;
oCOMThingy.AuthorizeEx (ref (object) sz);

...errors as "A ref or out argument must be an lvalue"=20

This suggests to me that I need to retriefe the address, but constructs
I have tried...

string sz;
oCOMThingy.AuthorizeEx (ref &((object) sz));

...generates several errors, including "Cannot take the address of the
given expression", and "A ref or out argument must be an lvalue".

[ ATTEMPT #3 ]
Falling back on old VB tactics, I tried...

private char[] mac1;
mac1 =3D " (long series of spaces) ".ToCharArray();
oCOMThingy.AuthorizeEx (ref (object) mac1);

... and the variation ...

oCOMThingy.AuthorizeEx (ref (object) mac1[1]);

... but I continue to receive the lvalue error.

What is the proper approach to this? Most of the code I have found
online suggests that the COM object methods should be specially formed
to support out data... but I would expect that there is an easy way to
integrate with legacy components in C#.

TIA

I have a legacy COM object thst

Reply to this message...
 
    
Ethan Selzer
Did you try:
string sz;
oCOMThingy.AuthorizeEx (ref sz);

Ethan

-----Original Message-----
From: Michael Wells [mailto:Click here to reveal e-mail address]
Sent: Wednesday, July 03, 2002 11:17 PM
To: aspngcs
Subject: [aspngcs] Passing C# strings by reference to a COM object

I am in the process of wrapping a legacy COM object in C# classes to
simplify integration with .NET. One of the methods on the object
requires three strings to be passed by reference, so that data can be
returned.

The call is of the form...

oCOMThingy.AuthorizeEx (ref object vrt1);

According to the docs, the call was designed so that it would work with
VB Script variants, when passed by reference. Since I'm new to C#, I'm
not certain how to approach this properly. (but, some of the cobwebs
are slowly falling away from my C++ experience)

[ ATTEMPT #1 ]
An "unannotated" call, such as...

string sz;
oCOMThingy.AuthorizeEx (sz);

...errors as "cannot convert from string to 'ref object'"

[ ATTEMPT #2 ]
Casting the param, as in...

string sz;
oCOMThingy.AuthorizeEx (ref (object) sz);

...errors as "A ref or out argument must be an lvalue"

This suggests to me that I need to retriefe the address, but constructs
I have tried...

string sz;
oCOMThingy.AuthorizeEx (ref &((object) sz));

...generates several errors, including "Cannot take the address of the
given expression", and "A ref or out argument must be an lvalue".

[ ATTEMPT #3 ]
Falling back on old VB tactics, I tried...

private char[] mac1;
mac1 = " (long series of spaces) ".ToCharArray();
oCOMThingy.AuthorizeEx (ref (object) mac1);

... and the variation ...

oCOMThingy.AuthorizeEx (ref (object) mac1[1]);

... but I continue to receive the lvalue error.

What is the proper approach to this? Most of the code I have found
online suggests that the COM object methods should be specially formed
to support out data... but I would expect that there is an easy way to
integrate with legacy components in C#.

TIA

I have a legacy COM object thst

| [aspngcs] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngcs.asp = JOIN/QUIT

Reply to this message...
 
    
Michael Wells

Yes, that was one of the variations of the "Attempt #1" approach that I
tried early on. It generates the same error as oCOMThingy.AuthorizeEx
(sz) does. However, I was able to find a partial solution by varying
Attempt #2...

[ ATTEMPT #4 ]

System.Object obj =3D "";
string sz;
oCOMThingy.AuthorizeEx (ref obj);
sz =3D obj.ToString();

Here, all of the compiler errors/warning disappear, and I am actually
able to receive my output data from the method call (wooHoo!).

Of course, the C programmer in me is screaming because the above code
should intuitively be writing data into uncharted waters. Since I
haven't experienced any problems yet, I have to ask... is the
System.Object allocation automatically expanded to hold the data? If
so, what's responsible for this... C#, .NET, the System.Object type,
Win32, or NT/2000? And how does it work? =20

Like any half-decent programmer, I'm not at all comfortable releasing
something that works for unknown reasons... but I'm even more concerned
about whether the app could break on other platforms.

Thanks again for any suggestions/explanations you can provide.

-- Michael Wells

[Original message clipped]

Reply to this message...
 
    
Andy Smith
it seems to me that whenever i've seen strings being passed into interop =
where the string will be changed... they've always used a StringBuilder =
instead of a String, because Strings are immutable and StringBuilders =
aren't.

but I must qualify that statement with "I have no clue how Interop =
works"

__
Andy Smith
Keyboard Jockey #3a7-2.78.1

[Original message clipped]

Reply to this message...
 
    
chris
The idea behind 'managed' code is that you don't have to worry about writing
code in uncharted waters...you have mr. garbage collector to deal with that
for you. I ran into a similar problem while trying to interop with a com
wrapper for a :\command line map engine - some of the methods I needed to
use for map 'layer' control required string& ref's. I just declared a string
object, and ended up passing its reference to a get_Item() method generated
by interop[tlbimp]. I have not run into any problems with this method.Also,
I ran this part of the app thru ACT, and she passed with flying colors.

From a C standpoint, sure - you are eating up a little more memory
explicitly storing an extra object in your IL.
From a .NET standpoint, forget about it. The performance hit you take should
be about the same as if you were using the com piece with no ref's; hey - at
least you don't have to build destructors and figure out when to ~destroy
your objects!

-----Original Message-----
From: Michael Wells [mailto:Click here to reveal e-mail address]
Sent: Friday, July 05, 2002 9:12 AM
To: aspngcs
Subject: [aspngcs] RE: Passing C# strings by reference to a COM object

Yes, that was one of the variations of the "Attempt #1" approach that I
tried early on. It generates the same error as oCOMThingy.AuthorizeEx
(sz) does. However, I was able to find a partial solution by varying
Attempt #2...

[ ATTEMPT #4 ]

System.Object obj = "";
string sz;
oCOMThingy.AuthorizeEx (ref obj);
sz = obj.ToString();

Here, all of the compiler errors/warning disappear, and I am actually
able to receive my output data from the method call (wooHoo!).

Of course, the C programmer in me is screaming because the above code
should intuitively be writing data into uncharted waters. Since I
haven't experienced any problems yet, I have to ask... is the
System.Object allocation automatically expanded to hold the data? If
so, what's responsible for this... C#, .NET, the System.Object type,
Win32, or NT/2000? And how does it work?

Like any half-decent programmer, I'm not at all comfortable releasing
something that works for unknown reasons... but I'm even more concerned
about whether the app could break on other platforms.

Thanks again for any suggestions/explanations you can provide.

-- Michael Wells

[Original message clipped]

| [aspngcs] member Click here to reveal e-mail address = YOUR ID
| http://www.asplists.com/asplists/aspngcs.asp = JOIN/QUIT

Reply to this message...
 
    
Joshua Perry
What is the type of the parameter for your AuthorizeEX method? The
default marshalling type for string is LPTSTR (TCHAR*) if you need LPSTR
(CHAR*) you will need to use the [MarshalAs(UnmanagedType.LPStr)]
attribute on the parameter to AuthorizeEx. The best way to pass
reference strings is to use StringBuilder. Eg.

[DllImport("user32.dll")]
public static extern int GetWindowText(    int hwnd,
                            StringBuilder
buf,
                            int nMaxCount
);

Don't forget that strings are immutable, anytime you do something to a
string, a new string is created.

Joshua Perry
1-800 CONTACTS, INC.
Information Systems Developer
(801)924-9828
=20

-----Original Message-----
From: Michael Wells [mailto:Click here to reveal e-mail address]=20
Sent: Friday, July 05, 2002 8:12 AM
To: aspngcs
Subject: [aspngcs] RE: Passing C# strings by reference to a COM object

Yes, that was one of the variations of the "Attempt #1" approach that I
tried early on. It generates the same error as oCOMThingy.AuthorizeEx
(sz) does. However, I was able to find a partial solution by varying
Attempt #2...

[ ATTEMPT #4 ]

System.Object obj =3D "";
string sz;
oCOMThingy.AuthorizeEx (ref obj);
sz =3D obj.ToString();

Here, all of the compiler errors/warning disappear, and I am actually
able to receive my output data from the method call (wooHoo!).

Of course, the C programmer in me is screaming because the above code
should intuitively be writing data into uncharted waters. Since I
haven't experienced any problems yet, I have to ask... is the
System.Object allocation automatically expanded to hold the data? If
so, what's responsible for this... C#, .NET, the System.Object type,
Win32, or NT/2000? And how does it work? =20

Like any half-decent programmer, I'm not at all comfortable releasing
something that works for unknown reasons... but I'm even more concerned
about whether the app could break on other platforms.

Thanks again for any suggestions/explanations you can provide.

-- Michael Wells

[Original message clipped]

| [aspngcs] member Click here to reveal e-mail address =3D YOUR ID
| http://www.asplists.com/asplists/aspngcs.asp =3D JOIN/QUIT

Reply to this message...
 
    
Michael Wells
Unfortunately, the intimate details of COM are unfamiliar to me, so you
might have top point me in the right direction. The TypeLib lists the
call as;

[id(0x0000003d), helpstring("method AuthorizeEx")]
HRESULT AuthorizeEx(
VARIANT* vrtAuthCode,=20
VARIANT* vrtErrorInfo,=20
VARIANT* vrtIsApproved);

And Visual Studio .NET describes it as...

    void TransactionInfoClass.AuthorizeEx (ref object vrtAuthCode,=20
        ref object vrtErrorInfo, ref object vrtIsApproved)

It makes sense to me that this would be interop's way of describing the
call in C#, since objects can be represent variants to a degree. =20

Out of curiosity, I attempted to use StringBuilder objects in place of
strings, and the compiler still seems unhappy...

    System.Text.StringBuilder sb1 =3D new System.Text.StringBuilder();

    oCOMThingy.AuthorizeEx (sb1);

=3D> cannot convert from 'System.Text.StringBuilder' to 'ref object'

    System.Text.StringBuilder sb1 =3D new System.Text.StringBuilder();

    oCOMThingy.AuthorizeEx (ref sb1);

=3D> cannot convert from 'ref System.Text.StringBuilder' to 'ref object'

    System.Text.StringBuilder sb1 =3D new System.Text.StringBuilder();

    oCOMThingy.AuthorizeEx (ref ((object) sb1));

=3D> a ref or out argument must be an lvalue

But I do understand the logic of using StringBuilder when a reference
string is expected.=20

I suspect that the developers' reason for using VARIANT* was to simplify
integration with VBScript apps. Much of the sample code for using the
component is ASP.=20

-- Michael Wells

[Original message clipped]

Reply to this message...
 
    
Joshua Perry
I apologize; I was thinking that you were trying to import a cdecl
function... duh...

When you make a reference to a COM object, Visual Studio runs tlbimp.exe
which creates a Runtime Callable Wrapper for your COM object. The RCW
dll has all of the marshalling code to move data between the COM object
and your managed code.

Now I'm not really a COM or .NET Interop master but what I think is
happening is what you may be familiar with as a C programmer is a
pointer to a pointer. When you pass the address of the object into the
com component it has another address "boxed" in it that the activex
control can then change to the pointer of the string it created.

You may also be able to do:

sz =3D (string)obj;

I'm not sure why whomever wrote your activex control would be looking
for a pointer coming in, especially if they were going to talk with VB
or the such.

You may want to change it to

[id(0x0000003d), helpstring("method AuthorizeEx")]
HRESULT AuthorizeEx(
VARIANT &vrtAuthCode,=20
VARIANT &vrtErrorInfo,=20
VARIANT &vrtIsApproved);

This way you should be able to do:

oComThingy.AuthorizeEx( sz1, sz2, sz3);

Let me know how it goes...

Joshua Perry
1-800 CONTACTS, INC.
Information Systems Developer
(801)924-9828
=20

-----Original Message-----
From: Michael Wells [mailto:Click here to reveal e-mail address]=20
Sent: Friday, July 05, 2002 3:28 PM
To: aspngcs
Subject: [aspngcs] RE: Passing C# strings by reference to a COM object

Unfortunately, the intimate details of COM are unfamiliar to me, so you
might have top point me in the right direction. The TypeLib lists the
call as;

[id(0x0000003d), helpstring("method AuthorizeEx")]
HRESULT AuthorizeEx(
VARIANT* vrtAuthCode,=20
VARIANT* vrtErrorInfo,=20
VARIANT* vrtIsApproved);

And Visual Studio .NET describes it as...

    void TransactionInfoClass.AuthorizeEx (ref object vrtAuthCode,=20
        ref object vrtErrorInfo, ref object vrtIsApproved)

It makes sense to me that this would be interop's way of describing the
call in C#, since objects can be represent variants to a degree. =20

Out of curiosity, I attempted to use StringBuilder objects in place of
strings, and the compiler still seems unhappy...

    System.Text.StringBuilder sb1 =3D new System.Text.StringBuilder();

    oCOMThingy.AuthorizeEx (sb1);

=3D> cannot convert from 'System.Text.StringBuilder' to 'ref object'

    System.Text.StringBuilder sb1 =3D new System.Text.StringBuilder();

    oCOMThingy.AuthorizeEx (ref sb1);

=3D> cannot convert from 'ref System.Text.StringBuilder' to 'ref object'

    System.Text.StringBuilder sb1 =3D new System.Text.StringBuilder();

    oCOMThingy.AuthorizeEx (ref ((object) sb1));

=3D> a ref or out argument must be an lvalue

But I do understand the logic of using StringBuilder when a reference
string is expected.=20

I suspect that the developers' reason for using VARIANT* was to simplify
integration with VBScript apps. Much of the sample code for using the
component is ASP.=20

-- Michael Wells

[Original message clipped]

| [aspngcs] member Click here to reveal e-mail address =3D YOUR ID
| http://www.asplists.com/asplists/aspngcs.asp =3D JOIN/QUIT

Reply to this message...
 
 
System.Object
System.Runtime.InteropServices.UnmanagedType
System.Text.StringBuilder




ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
Ad


Need Dot Net Interview Questions?
Ask ExamGuru, Inc. for advice and help on Passing .Net Interviews
.Net Projects
Best-of-breed application framework for .NET projects, developed by ExamGuru, Inc. and ExamGuru IT
Free .net Help
Commission ExamGuru, Inc. and his team for your next bespoke software project
FogBUGZ
The only bug tracking system carefully crafted with one goal in mind: helping teams create great software.
Awesome Tools
If you don't know about these, you're missing out... IT Certification Questions
IT Interview Questions
Free Oracle 10g Training
MCSE Boortcamp
Cisco Study Guides
Cheap Study Guides
Exact Questions
Dot Net Interview Questions
Oracle OCP
Cheap Travel
Designer Perfumes - Wholesale Prices
Free Programming Tutorials
 
ExamGuru IT Solutions - .Net Guru is owned and operated by ExamGuru, Inc., the man behind .Net Guru. If you're in the market for bespoke software or software consultancy, why not get him and his highly trained team to help? - www.examguru.net/ITCertification
 Copyright © ExamGuru, Inc. 2001-2006
Contact Us - Terms of Use - Privacy Policy - www.dot-net-guru.com - www.examguru.net - www.oraclesource.net - www.itinterviews.net - www.examguru.net/ITCertification