HOWTO: Marshal .Net Structure to VB

I am writing a C# class library that exposes a method that return a structure.  I am registering the assembly for COM interop and can reference the assembly in VB (Actually an Acces 2000 Code Module).  I can instantiate the object in VB but when I delcare the variable for the returning structure I get the following error.

         Variable uses and automation type not supported Visual Basic.

Also, if I declare the variable as an Object, the error occurs when I call the method.

Here is my code below...

-----------------------------------------------------------------------------------
C# Class
-----------------------------------------------------------------------------------

[GuidAttribute("B7D043BD-1003-4c6e-9050-0D0C4D93E213")]
      [ClassInterface(ClassInterfaceType.AutoDual)]
      public class VINDecoder
      {
      
            [GuidAttribute("201077FC-39A7-418e-A001-8AB69A3E52E4")]
            [StructLayout(LayoutKind.Sequential)]
            public struct VehicleInformation
            {      
                  [MarshalAs(UnmanagedType.LPWStr)]
                  public string Year;
                  [MarshalAs(UnmanagedType.LPWStr)]
                  public string Make;
                  [MarshalAs(UnmanagedType.LPWStr)]
                  public string Model;
                  [MarshalAs(UnmanagedType.LPWStr)]
                  public string MSRP;
            }

            public VINDecoder()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }

            public VehicleInformation Decode(string VIN)
            {
                  VehicleInformation vi = new VehicleInformation();
                  vi.Make = "Honda";
                  vi.Model = "Accord";
                  vi.Year = "2005";
                  vi.MSRP = "23000";
                  return vi;
            }

      }
}



---------------------------------------------------------------------------------------------------------
VB Code
---------------------------------------------------------------------------------------------------------

Public Function Test()

    Dim lVINDecoder As VINDecoder.VINDecoder
    Set lVINDecoder = New VINDecoder.VINDecoder
   
    Dim vi As VehicleInformation                                    '<--- Error occurs here
    Set vi = lVINDecoder.Decode("Test")

    Debug.Print vi.Make
End Function

Help code guru's!
mmurphy1005Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Chester_M_RagelCommented:
VB Code,

 Public Function Test()

        Dim lVINDecoder As VINDecoder
        lVINDecoder = New VINDecoder

        Dim vi As VINDecoder.VehicleInformation                                    
        vi = lVINDecoder.Decode("Test")

        MessageBox.Show(vi.Make)
  End Function
0
mmurphy1005Author Commented:
This did not work...

First, the Dim line threw up with out the project name.  I got a "Expected User-Defined type, not project" error
The next line required the same thing to specify the object, plus it requires a "Set" statement to instantiate the object first.

Puting the project name in front of VehicleInformation did nothing to help.

Chester: Did this actually work for you?
0
Chester_M_RagelCommented:
I always used to test the code efore posting. I made some changes to c# class as well. But I didn't post that. Sorry for that. The main point is that, when you refer a struct insite a class use the class name before the struct name.


using System;
using System.Runtime.InteropServices;

namespace VIN
{
      [GuidAttribute("B7D043BD-1003-4c6e-9050-0D0C4D93E213")]
      [ClassInterface(ClassInterfaceType.AutoDual)]
      public class VINDecoder
      {
     
            [GuidAttribute("201077FC-39A7-418e-A001-8AB69A3E52E4")]
                  [StructLayout(LayoutKind.Sequential)]
                  public struct VehicleInformation
            {    
                  [MarshalAs(UnmanagedType.LPWStr)]
                  public string Year;
                  [MarshalAs(UnmanagedType.LPWStr)]
                  public string Make;
                  [MarshalAs(UnmanagedType.LPWStr)]
                  public string Model;
                  [MarshalAs(UnmanagedType.LPWStr)]
                  public string MSRP;
            }

            public VINDecoder()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }

            public VehicleInformation Decode(string VIN)
            {
                  VehicleInformation vi = new VehicleInformation();
                  vi.Make = "Honda";
                  vi.Model = "Accord";
                  vi.Year = "2005";
                  vi.MSRP = "23000";
                  return vi;
            }

      }
}



--VB

Public Function Test()

        Dim lVINDecoder As VIN.VINDecoder
        lVINDecoder = New VIN.VINDecoder

        Dim vi As VIN.VINDecoder.VehicleInformation                                    '<--- Error occurs here
        vi = lVINDecoder.Decode("Test")

        Debug.Print vi.Make
End Function
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mmurphy1005Author Commented:
Thanks so much for responding to this question but I still have the error "Variable uses and automation type not supported Visual Basic."

I had tried using the MarshalAs and GuidAttribute on the structure previously, but since it didn't fix the issue, I removed it.

I noticed in your VB code changes you are prefixing the the class and struct with the namespace "VIN".
If I try to include the namespace first, I  get a "User Defined Type not Defined".  In object broswer I can see the project "VINDecoder" and the class "VINDecoder" but no refernces to just "VIN".  I can see the method and structure information of the class too.  When I write the code I can navigate the class layout with intellisense.  With one notable exception, I can see the properties of the structure in object browser, but I can not get them to pop up with intellisense.  This may be a sign as to why I can not refernce the VehicleInformation structure in VB.

I also am still getting an error if I do not use "Set" when I instantiate the VINDecoder class.

I also wanted to make sure you know I am running the VB code in Access 2000 (VBA)  but that shouldn't make a difference I believe.  

I ran the code in VB and recveived the same error.  
Thanks again for all you efforts, can you try your solution on your end in Access or Excel to see if you get the same error?
0
mmurphy1005Author Commented:
Well I posted the question on dotnet.languages.csharp newsgroup.  Nicholas Paldino, a .Net/C# MVP came up with the solution.

He said to change the MarshalAs attribute to UnManagedType.Bstr.  By doing this the error was resolved and I can now use intellisnse to access the vi structure attributes.

Thanks Nicholas

You the Man!

Chsester, I am awarding you the points since Nicholas is not in ee.  I sure appreciate your comments as I did incorporate some of your suggestions.

Mike Murphy
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.