3

I'm migrating some VB6 code to VB.net, the code contains a structure that contains 1d arrays, 2d arrays, and few other variables.

The general outline of the Vb.net structure is as under

Public Structure Test

    Dim a As Single
    Dim b As Single
    Dim c As Single
    <VBFixedArray(2)> Dim arr1() As Single
    <VBFixedArray(2, 2)> Dim mdarr1(,) As Single
    <VBFixedArray(4)> Dim arr2() As Byte
    <VBFixedArray(4)> Dim arr3() As Short
    <VBFixedArray(3, 2)> Dim mdarr2(,) As Integer

    Dim d As Integer
    Dim e As Decimal

End Structure

The call to the dll is declared as under

Public Declare Sub getState Lib "val.dll" (ByRef state As Test)

Elsewhere on this site I realized that we have to "marshal" the structure to allow it to be compatible with the unmanaged code that is about to accept it.

However I still receiving runtime errors when running the code, I don't have any clue of how to use the System.Runtime.InteropServices.Marshal class.

What would be the correct way to pass this structure to the dll?

EDIT:

The original VB6 data type is

Public Type Test

    a As Single
    b As Single
    c As Single
    arr1(0 To 2) As Single
    mdarr1(0 To 2, 0 To 2) As Single
    arr2(0 To 4) As Byte
    arr3(0 To 4) As Integer
    mdarr2(0 To 3, 0 To 2) As Long

    d As Long
    e As Currency

End Type
Community
  • 1
  • 1
Kevin Boyd
  • 12,121
  • 28
  • 86
  • 128

1 Answers1

1

Do you have the source code for getState in the val.dll? If it's written in C or C++, and you have the source code or even just the headers, you could use the P/Invoke Assistant to automatically generate your VB.Net code.

Alternatively... (and please do post the original VB6 structure!)

  • You might need to allocate the arrays before calling getState, e.g. state.arr1 = {0.0, 0.0} etc.
  • The Decimal variable e could cause you a problem. In VB6 this was probably a Currency variable, and Decimal is not an exact equivalent as far as I can remember. There will be a way to tell VB.Net to marshal it like a Currency. Perhaps adding an attribute like this...

Sample code:

 Imports System.Runtime  
 Public Structure Test  
   ''blah blah

   <InteropServices.MarshalAs(InteropServices.UnmanagedType.Currency)> _  
   Dim e As Decimal  

   ''blah blah
MarkJ
  • 30,070
  • 5
  • 68
  • 111
  • Yes, I have the .h file. It seems to be be C to me. I'm not that sure though. Sorry I'm not that conversant with .net, will look the p/invoke though. Original VB6 code posted!. Yes, the VS2008 upgrade wizard did add a initialize() in the structure, this function does a "redim" on the necessary arrays and inits it to the desired length. I didn't post that part for brevity – Kevin Boyd Feb 23 '11 at 08:13
  • Definitely run the .h file through the P/Invoke Assistant and see what it says. I see that `e` was a `Currency`, so I am pretty sure you need to marshal it as a currency as in my answer. You are *calling* the initialize(), right? :) You may also need to add some attributes to indicate how the arrays should be marshalled (they need to be marshalled as flat arrays). – MarkJ Feb 23 '11 at 09:02
  • By flat arrays do you mean that a 2d array should be marshaled as 1D array. in that case an array(2, 2) would become array(4) right? – Kevin Boyd Feb 23 '11 at 10:43
  • @Kevin perhaps I shouldn't have said "flat arrays". I meant that the values should all just be present in the memory for the structure in order, no pointers or handles or anything like that. If you looked at the memory for your structure you would see 4 bytes for a, 4 bytes for b, 4 bytes for c and then immediately 4 bytes for arr1(0) 4 bytes for arr1(1) 4 bytes for mdarr1(0,0) 4 bytes for mdarr1(0,1) etc etc – MarkJ Feb 23 '11 at 12:20