Properties only ByVal

O

Onno Ceelen

Hi,

I am testing interop code by use of some prototypes. What I have is the
following:

1. VB 6.0 library
2. VB.NET class library
3. Interop assembly of the VB 6.0 library (tlbimp output)

I want my VB.NET class library to have the exact same definition as my VB
6.0 library.

The code of VB 6.0 looks like the following (where, by default, newItemID is
passed in by reference):

Public Property Get ByVB6DefaultProperty() As String
ByRefProperty = mVB6DefaultProperty
End Property

Public Property Let ByVB6DefaultProperty(newItemID As String)
mVB6DefaultProperty = newItemID
End Property

When I generate an interop assembly by using tlbimp on the VB 6.0 dll, I get
the following IDL (ildasm view) for the set/let part of this property:

..method public hidebysig newslot specialname abstract virtual
instance void set_ByVB6DefaultProperty([in][out] string&
marshal( bstr) A_1) runtime managed internalcall
{
.custom instance void
[mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = (
01 00 00 00 03 68 00 00 ) // .....h..
} // end of method _ByRefProject::set_ByVB6DefaultProperty

Note that the parameter is still passed in by reference.

I tried to create a VB.NET assembly that has about the same IDL so it would
be able to replace my VB 6.0 library. Unfortunately for this situation, in
VB.NET you can't pass values by reference to the property: 'Set' parameter
cannot be declared 'ByRef'.

Is this a limitation which I should keep in mind and which forces me to take
another approach? I just moved from C# to VB.NET for this particular
assembly because I have to use optional parameters in methods (opposed to
overloaded methods).

If I reference my interop assembly namespace from my VB.NET project like:

Public Class SomeClassName
Implements ByRefProject.Interop._ByRefProject

The VS.NET IDE completes the code for me but immediately shows an error in
the generated code:

'dotNetProject.SomeClassName' must implement 'Overridable Property
ByVB6DefaultProperty() As String' for interface
'ByRefProject.Interop._ByRefProject'. Implementing property must have
matching 'ReadOnly'/'WriteOnly' specifiers.

Any idea why this is? Is it a limitation of the VB.Net languages or
something else?


Regards,

Onno Ceelen
 
C

Cor

Hi Onno,

No it is not possible to make dotnet Library for VB6.
While you also cannot make that with which other managed code language.

Cor
 
H

Herfried K. Wagner [MVP]

* "Onno Ceelen said:
1. VB 6.0 library
2. VB.NET class library
3. Interop assembly of the VB 6.0 library (tlbimp output)

I want my VB.NET class library to have the exact same definition as my VB
6.0 library.

The code of VB 6.0 looks like the following (where, by default, newItemID is
passed in by reference):

Public Property Get ByVB6DefaultProperty() As String
ByRefProperty = mVB6DefaultProperty
End Property

Public Property Let ByVB6DefaultProperty(newItemID As String)
mVB6DefaultProperty = newItemID
End Property

When I generate an interop assembly by using tlbimp on the VB 6.0 dll, I get
the following IDL (ildasm view) for the set/let part of this property:

.method public hidebysig newslot specialname abstract virtual
instance void set_ByVB6DefaultProperty([in][out] string&
marshal( bstr) A_1) runtime managed internalcall
{
.custom instance void
[mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = (
01 00 00 00 03 68 00 00 ) // .....h..
} // end of method _ByRefProject::set_ByVB6DefaultProperty

Note that the parameter is still passed in by reference.

I tried to create a VB.NET assembly that has about the same IDL so it would
be able to replace my VB 6.0 library. Unfortunately for this situation, in
VB.NET you can't pass values by reference to the property: 'Set' parameter
cannot be declared 'ByRef'.

Are you sure you want a 'ByRef' behavior? I don't understand why that
makes sense for 'Property Set'.
 
O

Onno Ceelen

It doesn't make sense to me too :)

The problem is that I don't want to touch my existing code. My existing code
uses (references) the VB 6.0 library mentioned in the example of my previous
e-mail. To be able to actually replace my VB 6.0 library with a .NET interop
assembly that has the same interface definition and implementation (but in
C# or VB.NET and using InteropServices attributes etc.) I have to adhere to
the the previous interface created in VB 6.0.

But, if in VB 6.0 you had a property defined as:

Public Property Let ByVB6DefaultProperty(newItemID As String)
mVB6DefaultProperty = newItemID
End Property

the newItemID is passed in ByRef (just because the one who coded this didn't
specify ByVal).

I can't do that in VB.NET.

My question is, am I right about this, that you could pass property values
ByRef in VB 6.0 but can't do that anymore in VB.NET? Does C# allow this?

All I want is to produce the following IDL for my interface with either
VB.NET or C# (interop):

interface _ByRefProject : IDispatch {
[id(0x68030002), propget]
HRESULT ByValProperty([out, retval] BSTR* );
[id(0x68030002), propput]
HRESULT ByValProperty([in] BSTR );
[id(0x68030001), propget]
HRESULT ByRefProperty([out, retval] BSTR* );
[id(0x68030001), propput]
HRESULT ByRefProperty([in, out] BSTR* );
[id(0x68030000), propget]
HRESULT ByVB6DefaultProperty([out, retval] BSTR* );
[id(0x68030000), propput]
HRESULT ByVB6DefaultProperty([in, out] BSTR* );
};

Thanks,

Onno

Herfried K. Wagner said:
* "Onno Ceelen said:
1. VB 6.0 library
2. VB.NET class library
3. Interop assembly of the VB 6.0 library (tlbimp output)

I want my VB.NET class library to have the exact same definition as my VB
6.0 library.

The code of VB 6.0 looks like the following (where, by default, newItemID is
passed in by reference):

Public Property Get ByVB6DefaultProperty() As String
ByRefProperty = mVB6DefaultProperty
End Property

Public Property Let ByVB6DefaultProperty(newItemID As String)
mVB6DefaultProperty = newItemID
End Property

When I generate an interop assembly by using tlbimp on the VB 6.0 dll, I get
the following IDL (ildasm view) for the set/let part of this property:

.method public hidebysig newslot specialname abstract virtual
instance void set_ByVB6DefaultProperty([in][out] string&
marshal( bstr) A_1) runtime managed internalcall
{
.custom instance void
[mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = (
01 00 00 00 03 68 00 00 ) // .....h..
} // end of method _ByRefProject::set_ByVB6DefaultProperty

Note that the parameter is still passed in by reference.

I tried to create a VB.NET assembly that has about the same IDL so it would
be able to replace my VB 6.0 library. Unfortunately for this situation, in
VB.NET you can't pass values by reference to the property: 'Set' parameter
cannot be declared 'ByRef'.

Are you sure you want a 'ByRef' behavior? I don't understand why that
makes sense for 'Property Set'.
 
J

Jay B. Harlow [MVP - Outlook]

Herfried & Onno,
Are you sure you want a 'ByRef' behavior? I don't understand why that
makes sense for 'Property Set'.
I'm strongly suspect he does not want "ByRef"! If he does he needs to read
about side-effects in methods! And why they should be avoided.

Remember ByRef is the default if you do not specify ByRef or ByVal in VB6.
Looking at his code, he did not specify, so it defaults to ByRef!

I would recommend to Onno, if he has the VB6 library to run the Visual Basic
6.0 Code Advisor, on his VB6 project, make the corrections then recompile it
as a VB6 library:

http://msdn.microsoft.com/vbasic/downloads/codeadvisor/default.aspx

Of course this means he will need to recompile any VB6 projects that
reference it, alternatively Onno could create a VB6 shim project (wrapper)
that corrects the parameters that is used by VB.NET, while keeping the
original VB6 library intact. The wrapper may be the easier route, especially
if the VB6 project does not change. Of course the wrapper means you are
going through 2 extra layers (the wrapper and the interop).

Hope this helps
Jay


Herfried K. Wagner said:
* "Onno Ceelen said:
1. VB 6.0 library
2. VB.NET class library
3. Interop assembly of the VB 6.0 library (tlbimp output)

I want my VB.NET class library to have the exact same definition as my VB
6.0 library.

The code of VB 6.0 looks like the following (where, by default, newItemID is
passed in by reference):

Public Property Get ByVB6DefaultProperty() As String
ByRefProperty = mVB6DefaultProperty
End Property

Public Property Let ByVB6DefaultProperty(newItemID As String)
mVB6DefaultProperty = newItemID
End Property

When I generate an interop assembly by using tlbimp on the VB 6.0 dll, I get
the following IDL (ildasm view) for the set/let part of this property:

.method public hidebysig newslot specialname abstract virtual
instance void set_ByVB6DefaultProperty([in][out] string&
marshal( bstr) A_1) runtime managed internalcall
{
.custom instance void
[mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = (
01 00 00 00 03 68 00 00 ) // .....h..
} // end of method _ByRefProject::set_ByVB6DefaultProperty

Note that the parameter is still passed in by reference.

I tried to create a VB.NET assembly that has about the same IDL so it would
be able to replace my VB 6.0 library. Unfortunately for this situation, in
VB.NET you can't pass values by reference to the property: 'Set' parameter
cannot be declared 'ByRef'.

Are you sure you want a 'ByRef' behavior? I don't understand why that
makes sense for 'Property Set'.
 
J

Jay B. Harlow [MVP - Outlook]

Onno,
I have to adhere to
the the previous interface created in VB 6.0.
See my other post, I would recommend the wrapper if you are NOT allowed to
fix the VB6 class library.
My question is, am I right about this, that you could pass property values
ByRef in VB 6.0 but can't do that anymore in VB.NET? Does C# allow this?
You are correct VB6 allowed it, while .NET does not. You could try C# to see
it its allowed, however I don't think so as C# requires you to use "ref"
keyword when passing ByRef parameters...

I don't remember specifically, Adam Nathan's book ".NET and COM - The
Complete Interoperability Guide" from MS Press. May have an example of how
to get what you got to work. I know he discusses how to create & "improve"
the interop assemblies.

Hope this helps
Jay


Hope this helps
Jay

Onno Ceelen said:
It doesn't make sense to me too :)

The problem is that I don't want to touch my existing code. My existing code
uses (references) the VB 6.0 library mentioned in the example of my previous
e-mail. To be able to actually replace my VB 6.0 library with a .NET interop
assembly that has the same interface definition and implementation (but in
C# or VB.NET and using InteropServices attributes etc.) I have to adhere to
the the previous interface created in VB 6.0.

But, if in VB 6.0 you had a property defined as:

Public Property Let ByVB6DefaultProperty(newItemID As String)
mVB6DefaultProperty = newItemID
End Property

the newItemID is passed in ByRef (just because the one who coded this didn't
specify ByVal).

I can't do that in VB.NET.

My question is, am I right about this, that you could pass property values
ByRef in VB 6.0 but can't do that anymore in VB.NET? Does C# allow this?

All I want is to produce the following IDL for my interface with either
VB.NET or C# (interop):

interface _ByRefProject : IDispatch {
[id(0x68030002), propget]
HRESULT ByValProperty([out, retval] BSTR* );
[id(0x68030002), propput]
HRESULT ByValProperty([in] BSTR );
[id(0x68030001), propget]
HRESULT ByRefProperty([out, retval] BSTR* );
[id(0x68030001), propput]
HRESULT ByRefProperty([in, out] BSTR* );
[id(0x68030000), propget]
HRESULT ByVB6DefaultProperty([out, retval] BSTR* );
[id(0x68030000), propput]
HRESULT ByVB6DefaultProperty([in, out] BSTR* );
};

Thanks,

Onno

I
get
the following IDL (ildasm view) for the set/let part of this property:

.method public hidebysig newslot specialname abstract virtual
instance void set_ByVB6DefaultProperty([in][out] string&
marshal( bstr) A_1) runtime managed internalcall
{
.custom instance void
[mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32)
=
situation,
 

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