Re: Passing VB.NET classes as arguments to VC7 DLLs.
"Patrick Ireland" <ireland@airmail.net> wrote in message
news:3aa0579c$1@news.devx.com...
>
> I have encountered a problem with passing data elements in a class to
> a DLL. The data is marshalled and sequential so the data appears correct
> to the DLL however when I update field in the DLL the change is not
> mapped back to the VB7 app.
....
> What did I miss?
You are passing the structure by-value(a copy is placed on the stack), not
by reference, thus the copy worked with on the VC7 side is not the one on
the VB.NET side, so your changes will not, and should not, be reflected
back.
If you change the C++ function to tkae a pointer to this structure (or a
reference), and then change the declaration in your vb code to be byref, you
should get the behavior you are expecting.
Re: Passing VB.NET classes as arguments to VC7 DLLs.
Hi Jeff,
Did you get my email?
As to your response I should have included the code from C++
typedef struct
{
int intAccessStatus;
BYTE abytUserName [ 20 ];
} TestPassing;
DWORD __stdcall AccessTestPassing
(int intAccessType,
TestPassing * pTestPassing)
{
}
The ByVal was selected because if I used ByRef I do not get the data. I
suspect that I get a pointer to a pointer to the structure data.
As you can see the data is received at the DLL as a ptr to the data and
this aspect works correctly.
I did try a ByRef with the above C++ code and I died in a smoking hole.
Perhaps I should try ** in the DLL but it should not be a required.
I repeat is there something I'm missing in the VB that remaps that data
back to the original VB layout. I know in VB6 I must pass string arrays
as ByVal. But UDT I pass ByRef.
I also agree that the data is probably placed on the stack, however, it
still does explain why a ptr reference is required. I do want to modify
the data and therefore I want a ptr refence in the C++, but passing the
entire structure on the stack is inconsistent with the requirement of a
ptr reference. I pretty sure you followed that jumbled sentence.
I will try the ** reference in the C++ module however as a purest that
doesn't seem like quit the correct solution.
Thanks for the response in any case. I'll keep you informed. ;8-)
"Jeff Peil" <jpeil@bigfoot.com> wrote:
>
>"Patrick Ireland" <ireland@airmail.net> wrote in message
>news:3aa0579c$1@news.devx.com...
>>
>> I have encountered a problem with passing data elements in a class to
>> a DLL. The data is marshalled and sequential so the data appears correct
>> to the DLL however when I update field in the DLL the change is not
>> mapped back to the VB7 app.
>....
>
>> What did I miss?
>
>You are passing the structure by-value(a copy is placed on the stack), not
>by reference, thus the copy worked with on the VC7 side is not the one on
>the VB.NET side, so your changes will not, and should not, be reflected
>back.
>
>If you change the C++ function to tkae a pointer to this structure (or a
>reference), and then change the declaration in your vb code to be byref,
you
>should get the behavior you are expecting.
>
>
>
>
Re: Passing VB.NET classes as arguments to VC7 DLLs.
Hi Patrick,
"Patrick Ireland" <ireland@airmail.net> wrote in message
news:3aa08054$1@news.devx.com...
> The ByVal was selected because if I used ByRef I do not get the data. I
> suspect that I get a pointer to a pointer to the structure data.
Doh, I completely overlooked that you were using a class and not a
structure. IIRC this is broken for VB.NET in beta 1 because the out
attribute is not properly supported by the compiler (however it does work
for a structure passed byref which will give the same semantics as a class
passed byval in your case.)
This does work in C# and ME C++* with a managed class for the parameter as
the beta 1 compiler because those languages does support the out attribute
properly.
* Beta 1 ME C++ does not properly attribute parameters for global methods,
but it will work when used on a static member of a managed type.
Anyways try chaning your VB code to
Public Structure <StructLayout(LayoutKind.Sequential)> DATA_TestPassing
' AccessStatus INT
Public AccessStatus As Integer
' UserName CHAR (16)
Public <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> UserName()
As Byte
End Structure
and
Private Declare Function AccessTestPassing _
Lib "c:\Pat\VS7\EXE\TestPassing" _
(ByVal intAccessType As Integer, _
ByRef REC_TestPassing As DATA_TestPassing) _
As Integer
Of course keep in mind that a freshly created DATA_TestPassing will not have
it's array initialized (you'll want to manually initialize the array on the
managed side of things before using it.)
Re: Passing VB.NET classes as arguments to VC7 DLLs.
Hi Jeff,
Thanks for the timely response. However, I have already tried the
structure method:
Public Structure <StructLayout(LayoutKind.Sequential)> DATA_TestPassing
Public AccessStatus As Integer
Public <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> UserName()
As Byte
End Structure
VB.NET gives the error message:
"Array initializers are not allowed on a field in a structure"
So it seems like a Catch-22. Of course I could have the marshal statement
incorrect for the array of bytes.
Your comment about filling out the array is very appropriate. I found that
I had to fill every position with something and I could not do it by array
subscripting. I filled the array with the System.Text.ASCIIEncoding ().
I am disappointed it that I can not find a equivalent to the VB6-- function
String$(10,Chr(0)) that produces a string of 10 null characters or what
ever character is the second argument. Do you know of one?
As always, Jeff you have been the horn of plenty for information but
sadly this time the suggested feature has a problem. Admittedly, the
problem may be between the ears of this typist.
"Jeff Peil" <jpeil@bigfoot.com> wrote:
>Hi Patrick,
>
>"Patrick Ireland" <ireland@airmail.net> wrote in message
>news:3aa08054$1@news.devx.com...
>> The ByVal was selected because if I used ByRef I do not get the data.
I
>> suspect that I get a pointer to a pointer to the structure data.
>
>Doh, I completely overlooked that you were using a class and not a
>structure. IIRC this is broken for VB.NET in beta 1 because the out
>attribute is not properly supported by the compiler (however it does work
>for a structure passed byref which will give the same semantics as a class
>passed byval in your case.)
>
>This does work in C# and ME C++* with a managed class for the parameter
as
>the beta 1 compiler because those languages does support the out attribute
>properly.
>
>* Beta 1 ME C++ does not properly attribute parameters for global methods,
>but it will work when used on a static member of a managed type.
>
>
>Anyways try chaning your VB code to
>
>Public Structure <StructLayout(LayoutKind.Sequential)> DATA_TestPassing
> ' AccessStatus INT
> Public AccessStatus As Integer
> ' UserName CHAR (16)
> Public <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> UserName()
>As Byte
>End Structure
>
>and
>
>
> Private Declare Function AccessTestPassing _
> Lib "c:\Pat\VS7\EXE\TestPassing" _
> (ByVal intAccessType As Integer, _
> ByRef REC_TestPassing As DATA_TestPassing) _
> As Integer
>
>Of course keep in mind that a freshly created DATA_TestPassing will not
have
>it's array initialized (you'll want to manually initialize the array on
the
>managed side of things before using it.)
>
>
Re: Passing VB.NET classes as arguments to VC7 DLLs.
Hi Patrick,
I knew there was a problem in beta 1 with ref types not being updated properly,
but I thought this was only with Paramarrays. Apperently, you found out otherwise
:)
I'll have to remember that.
But the point is that it's a known limitation with Beta1, so don't go and
change all your DLL's right away. The problem should be fixed soon.
Anyway, you no longer need a String() function. The string class has a constructor
to do what you want:
MyString = new String (MyChar, 10)
-Rob
"Patrick Ireland" <ireland@airmail.net> wrote:
>
>Hi Jeff,
>
>Thanks for the timely response. However, I have already tried the
>structure method:
>
>Public Structure <StructLayout(LayoutKind.Sequential)> DATA_TestPassing
> Public AccessStatus As Integer
> Public <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> UserName()
>As Byte
>End Structure
>
>VB.NET gives the error message:
>
>"Array initializers are not allowed on a field in a structure"
>
>So it seems like a Catch-22. Of course I could have the marshal statement
>incorrect for the array of bytes.
>
>Your comment about filling out the array is very appropriate. I found that
>I had to fill every position with something and I could not do it by array
>subscripting. I filled the array with the System.Text.ASCIIEncoding ().
>
>I am disappointed it that I can not find a equivalent to the VB6-- function
>String$(10,Chr(0)) that produces a string of 10 null characters or what
>ever character is the second argument. Do you know of one?
>
>As always, Jeff you have been the horn of plenty for information but
>sadly this time the suggested feature has a problem. Admittedly, the
>problem may be between the ears of this typist.
>
>"Jeff Peil" <jpeil@bigfoot.com> wrote:
>>Hi Patrick,
>>
>>"Patrick Ireland" <ireland@airmail.net> wrote in message
>>news:3aa08054$1@news.devx.com...
>>> The ByVal was selected because if I used ByRef I do not get the data.
> I
>>> suspect that I get a pointer to a pointer to the structure data.
>>
>>Doh, I completely overlooked that you were using a class and not a
>>structure. IIRC this is broken for VB.NET in beta 1 because the out
>>attribute is not properly supported by the compiler (however it does work
>>for a structure passed byref which will give the same semantics as a class
>>passed byval in your case.)
>>
>>This does work in C# and ME C++* with a managed class for the parameter
>as
>>the beta 1 compiler because those languages does support the out attribute
>>properly.
>>
>>* Beta 1 ME C++ does not properly attribute parameters for global methods,
>>but it will work when used on a static member of a managed type.
>>
>>
>>Anyways try chaning your VB code to
>>
>>Public Structure <StructLayout(LayoutKind.Sequential)> DATA_TestPassing
>> ' AccessStatus INT
>> Public AccessStatus As Integer
>> ' UserName CHAR (16)
>> Public <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> UserName()
>>As Byte
>>End Structure
>>
>>and
>>
>>
>> Private Declare Function AccessTestPassing _
>> Lib "c:\Pat\VS7\EXE\TestPassing" _
>> (ByVal intAccessType As Integer, _
>> ByRef REC_TestPassing As DATA_TestPassing) _
>> As Integer
>>
>>Of course keep in mind that a freshly created DATA_TestPassing will not
>have
>>it's array initialized (you'll want to manually initialize the array on
>the
>>managed side of things before using it.)
>>
>>
>
Re: Passing VB.NET classes as arguments to VC7 DLLs.
"Patrick Ireland" <ireland@airmail.net> wrote in message
news:3aa10461$1@news.devx.com...
>
> Hi Jeff,
>
> Thanks for the timely response. However, I have already tried the
> structure method:
>
> Public Structure <StructLayout(LayoutKind.Sequential)> DATA_TestPassing
> Public AccessStatus As Integer
> Public <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> UserName()
> As Byte
> End Structure
>
> VB.NET gives the error message:
>
> "Array initializers are not allowed on a field in a structure"
Are you sure you didn't accidently leave the 20 inside of the parens?
You'll notice the above shows UserName() without a size inside the parens.
As it is listed above, it worked for me with the Beta1 version of VBC.
> Your comment about filling out the array is very appropriate. I found
that
> I had to fill every position with something and I could not do it by array
> subscripting. I filled the array with the System.Text.ASCIIEncoding ().
Actually I was referring to needing to redim the array before using it, when
you define the structure. That is, once you have your instance of the
structure, you'd need/want to redim the array to create it (as you initially
have a reference to a null-array object on the managed side of things when
you create an instance of your structure.)
> I am disappointed it that I can not find a equivalent to the VB6--
function
> String$(10,Chr(0)) that produces a string of 10 null characters or what
> ever character is the second argument. Do you know of one?
See the String class' constructor that takes a char and a length.
Re: Passing VB.NET classes as arguments to VC7 DLLs.
Hi Jeff,
Amazing how things work once I get an explanation from a Guru. Now I
understand the problem of object definition within structures and classes
that are passed. Not only must you instantiate the structure or class
but also the objects within the structure or class. And in the world of
VB6-- and C/C++ arrays are NOT objects per se. Old habits in a new
environment. I even knew this and still made the mistake.
Thanks again 8-)
"Jeff Peil" <jpeil@bigfoot.com> wrote:
>
>"Patrick Ireland" <ireland@airmail.net> wrote in message
>news:3aa10461$1@news.devx.com...
>>
>> Hi Jeff,
>>
>> Thanks for the timely response. However, I have already tried the
>> structure method:
>>
>> Public Structure <StructLayout(LayoutKind.Sequential)> DATA_TestPassing
>> Public AccessStatus As Integer
>> Public <MarshalAs(UnmanagedType.ByValArray, SizeConst:=20)> UserName()
>> As Byte
>> End Structure
>>
>> VB.NET gives the error message:
>>
>> "Array initializers are not allowed on a field in a structure"
>
>Are you sure you didn't accidently leave the 20 inside of the parens?
>You'll notice the above shows UserName() without a size inside the parens.
>As it is listed above, it worked for me with the Beta1 version of VBC.
>
>> Your comment about filling out the array is very appropriate. I found
>that
>> I had to fill every position with something and I could not do it by array
>> subscripting. I filled the array with the System.Text.ASCIIEncoding ().
>
>Actually I was referring to needing to redim the array before using it,
when
>you define the structure. That is, once you have your instance of the
>structure, you'd need/want to redim the array to create it (as you initially
>have a reference to a null-array object on the managed side of things when
>you create an instance of your structure.)
>
>> I am disappointed it that I can not find a equivalent to the VB6--
>function
>> String$(10,Chr(0)) that produces a string of 10 null characters or what
>> ever character is the second argument. Do you know of one?
>
>See the String class' constructor that takes a char and a length.
>
>
>