Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / June 2005

Tip: Looking for answers? Try searching our database.

Marshaling 2-Dim Arrays

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
rmacias - 10 Jun 2005 23:22 GMT
I am currently writing a C# app replacing an old app written in VB6.  Part of
the app save it's structure contents to a binary file.  The old VB6 app dumps
the structure into the file via:

    Put #Fnumb, , MyVB6Structure

It is critial for my app that I write to this binary file in the same format
as the old VB6 app did because another VB6 will be reading the file generated
by my new app.

Inside my C# app, I have the old VB6 structure defined as follows:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    public class MyVB6StructureInCSharp
    {
        public float myfloat1;
        public int myInt1;
       
        [MarshalAs(UnmanagedType.SafeArray)]
        public bool[,] TwoDimArrayOfBool;

        [MarshalAs(UnmanagedType.BStr, SizeConst = 255)]
        public string myString;

    }//end of class TimingType1

During my save function, I am able to create an instance of this class and
populate it with the appropiate data.  I then want to take this class and
then write it to a binary file (in the same format that VB6 does it).  The
approach I am using is that I want to take the class and convert it into an
unmanaged array of bytes, and write this byte array to the binary file.  I
convert the class into an an array of bytes as follows:

private byte[] StructureToBytes(MyVB6StructureInCSharp myStruct)
        {
            int size;
            IntPtr p;
            byte[] ret;

            //The line below generates an exception:
                                              //can not be marshaled as an
unmanaged
                                              //structure; no meaningful
size or offset can be
                                              //computed.
                                              size =
Marshal.SizeOf(myStruct.GetType());
            p = Marshal.AllocCoTaskMem(size);

            try
            {
                Marshal.StructureToPtr(timingStruct, p, false);

                //Copy the unmanaged structure pointer into an array of bytes.
                ret = new byte[size];
                Marshal.Copy(p, ret, 0, size);
            }
            finally
            {
                //clean up our little mess.
                Marshal.FreeCoTaskMem(p);
            }

            //return the bytes
            return ret;

        }

When I perform the "size = Marshal.SizeOf(myStruct.GetType());" command I
get an exception that tells me that it can not marshal the structure as an
unmanaged structure becasue no size or offset can be determined.  I have
narrowed down the problem to be the 2 dimensional array of booleans that is
defined in my class.  It appears that the problem is that.

So my question is how can I properly marshal a two dimensional array of
booleans, to that I can convert the class into an array of bytes to write to
a binary file.  Any help would be appreciated.

Thanks!
Kevin Yu [MSFT] - 11 Jun 2005 03:39 GMT
Hi,

We have reviewed this issue and are currently researching on it. We will
update you ASAP. Thanks for your patience!

Kevin Yu
Signature

=======
"This posting is provided "AS IS" with no warranties, and confers no
rights."

"Peter Huang" [MSFT] - 13 Jun 2005 04:28 GMT
Hi

We can not marshal a structure with a two dimensions array inside, we need
to treat it as a single dimension array.
Here is a link for your reference.
http://groups-beta.google.com/group/microsoft.public.dotnet.framework.intero
p/browse_thread/thread/68033197c75729be/912194d8cf731236?q=MVP+Marshal+two+d
imensions+group:microsoft.public.dotnet.framework.interop&rnum=1&hl=en#91219
4d8cf731236

If you still have any concern, can you post your vb6 structure and the code
your use to serialize to the disk,  a simple vb6 project will be preferred.

Best regards,

Peter Huang
Microsoft Online Partner Support

Signature

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

Yan-Hong Huang[MSFT] - 15 Jun 2005 10:16 GMT
Hello,

I am reviewing this issue thread. Do you have any more concerns on Peter's
reply? If there is any unclear, please feel free to reply here and we will
follow up.

Thanks very much for participating the community.

Best regards,
Yanhong Huang
Microsoft Community Support

Get Secure! ¨C www.microsoft.com/security
Register to Access MSDN Managed Newsgroups!
-http://support.microsoft.com/default.aspx?scid=/servicedesks/msdn/nospam.as
p&SD=msdn

This posting is provided "AS IS" with no warranties, and confers no rights.
rmacias - 15 Jun 2005 17:01 GMT
Thanks for all your replies.  

I have tried to marshal it as a 1-Dim array.  It writes it to disk as a
one-dim array, but when the VB6 "Loader" app reads the binary file, I reads
in the entire structure at the same time.  All fields in the structure get
populated correctly, except for the (now) 1-Dim array.  I suspect that it is
expecting it be a 2-Dim array.  

Since Marshaling a 2-dim array is not possible, I need a way to simulate
marshaling a 2-dim array.  Using a Binary Editor, when VB6 writes a structure
that has a two dim array to a binary file, there appears to be some sort of
"header" (an extra 18 bytes) in front of the start of the array data.  I
suspect that these extra bytes define how the 2-Dim array is structured.

Can you verify how VB6 writes a structure containing a 2-dim array?  What
are these extra bytes?  If I can simulate this somehow, this will probably
get me going.

Thanks!

> Hello,
>
[quoted text clipped - 14 lines]
>
> This posting is provided "AS IS" with no warranties, and confers no rights.
"Peter Huang" [MSFT] - 16 Jun 2005 08:22 GMT
Hi

Here is my code to serialize the struture in vb6.
Private Type Record
ID As Long
TwoDimArrayOfBool(2, 2) As Boolean
End Type

Private Sub Command1_Click()
Dim MyRecord As Record
MyRecord.ID = 17
Dim i As Integer
Dim j As Integer
For i = 0 To 1
   For j = 0 To 2
       MyRecord.TwoDimArrayOfBool(i, j) = True
   Next
Next
For j = 0 To 2
   MyRecord.TwoDimArrayOfBool(2, j) = False
Next
Open "c:\TESTFILE.dat" For Random As #1 Len = Len(MyRecord)
Put #1, , MyRecord   ' Write record to file.
Close #1   ' Close file.
End Sub

Because in vb6, Boolean variables are stored as 16-bit (2-byte) numbers.

The output is as below.
11 00 00 00 FF FF FF FF 00 00 FF FF FF FF 00 00 FF FF FF FF 00 00

11 00 00 00 'Long 4bytes

FF FF FF FF 00 00 FF FF FF FF 00 00 FF FF FF FF 00 00 ' 3X3X2 ,because a
boolean is stored as 2 bytes in vb6.

So there is no header in the dump file.

Did I missing something?

Best regards,

Peter Huang
Microsoft Online Partner Support

Signature

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.

rmacias - 17 Jun 2005 02:50 GMT
Peter, thank you for your responses.  I did forget to mention something.  You
are correct with the code you posted.  However, what I forgot to mention (my
apologies) is that the two Dim array of booleans are created dynamically, and
not statically.  Here is how to simulate what I have:

Public Type Dynamic2DimArray

   TwoDimArrayOfBool() As Boolean

End Type

Private Sub Command1_Click()

   Dim dynamicRecord As Dynamic2DimArray
   Dim i As Integer
   Dim j As Integer

   ReDim dynamicRecord.TwoDimArrayOfBool(2, 2)
   
   For i = 0 To 1
       For j = 0 To 2
           dynamicRecord.TwoDimArrayOfBool(i, j) = True
       Next
   Next
   
   For j = 0 To 2
       dynamicRecord.TwoDimArrayOfBool(2, j) = False
   Next

   Open "C:\DynamicArray.dat" For Random As #2
   Put #2, , dynamicRecord
   Close #2

End Sub

In a hex editor, the result is as follows:

02 00 03 00 00 00 00 00 00 00 03 00 00 00 00 00 00 00 ff ff ff ff 00 00 ff
ff ff ff 00 00 ff ff ff ff 00 00

The last 18 bytes is the two dim array (same results you got from your
test).  However, there is an extra 18 bytes before the data.  I suspect that
this is some sort of "header" that describes the dimensions of the two dim
array.  I need to know what the format of this "header" is (if it is even a
header).  If I can simulate writing these extra 18 bytes, my c# program will
be able to write in the exact format as the old application does.

Thanks your efforts.  I really appreciate it!

> Hi
>
[quoted text clipped - 43 lines]
> Get Secure! - www.microsoft.com/security
> This posting is provided "AS IS" with no warranties, and confers no rights.
"Peter Huang" [MSFT] - 17 Jun 2005 09:16 GMT
Hi

Thanks for your quickly reply!
Based on my research, the internal array structure of vb6 is not public.
So far as a workaround I think we may call the vb code in c# to workaround
the problem.

Add reference to
Assembly microsoft.visualbasic
   c:\windows\microsoft.net\framework\v1.1.4322\microsoft.visualbasic.dll

using Microsoft.VisualBasic;

public struct Dynamic2DimArray
{
    public Boolean[,] TwoDimArrayOfBool; //definition
}

private void button1_Click(object sender, System.EventArgs e)
{
    Dynamic2DimArray dda = new Dynamic2DimArray();
    dda.TwoDimArrayOfBool =new Boolean[2,2];
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            dda.TwoDimArrayOfBool[i,j]=true;
    FileSystem.FileOpen(1, @"C:\DynamicArray4.dat",
OpenMode.Random,OpenAccess.Default,OpenShare.Default,-1);
    FileSystem.FilePut(1, dda,-1);
    FileSystem.FileClose(1);
}

Best regards,

Peter Huang
Microsoft Online Partner Support

Signature

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.