Re: Passing VB.NET classes as arguments to VC7 DLLs.


DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Results 1 to 7 of 7

Thread: Re: Passing VB.NET classes as arguments to VC7 DLLs.

  1. #1
    Jeff Peil Guest

    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.





  2. #2
    Patrick Ireland Guest

    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.
    >
    >
    >
    >



  3. #3
    Jeff Peil Guest

    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.)



  4. #4
    Patrick Ireland Guest

    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.)
    >
    >



  5. #5
    Rob Teixeira Guest

    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.)
    >>
    >>

    >



  6. #6
    Jeff Peil Guest

    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.




  7. #7
    Patrick Ireland Guest

    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.
    >
    >
    >



Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center