Call C# Code from C++ and read an array of struct which contains strings

Introduction

My C++ code was trying to read an array of struct which contains string data in C# . To my surprise, I found that a struct array which contains only integer is very easy to get, but if you have a string in the array, you need to do some more thing. I searched in the google, and a lot of people talked about the same problem as they are getting the exception which says, �Old format or invalid type library�. But no where I was able to find the answer, so since I was able to solve the problem, I am publishing it.

 

Basic Ideas

 

          I have a c# dll which contains a struct, lets say

 

public struct MyStruct

      {

        public string name;

        public string surname;

        public int age;

      }

 

      I have an interface which looks like this

     

      public interface ITest

      {       

        MyStruct[] GetData       

        {

            get;

        }

      }

 

      And my main class is

 

      public class Test : ITest

      {

       

        MyStruct[] st = new MyStruct[2];

        public Test()

        {

            st[0].name = "abc";

            st[0].surname = "def";

            st[0].age = 10;

 

            st[1].name = "qwe";

            st[1].surname = "rty";

            st[1].age = 20;

        }

 

        public MyStruct[] GetData

        {

            get

            {

                return st;

            }

 

        }        

      }

 

          Now build the dll. Then from the visual studio command prompt type type �regasm MyInterOp.dll /tlb:MyInterOp.tlb�.

       

        Have look at the tlb using OleViewer

 

 

See the tagMyStruct. It have LPSTR.

 

Now create a console application in C++. It looks like this

 

HRESULT hr = CoInitialize(NULL);

        ITest* pTest = NULL;

hr = CoCreateInstance(__uuidof(Test),NULL,CLSCTX_INPROC_SERVER,__uuidof(ITest),(void**)&pTest);

 

        MyInterOp::MyStruct HUGEP *pBSTR;

 

hr = SafeArrayAccessData(pTest->GetData, (void HUGEP* FAR*)&pBSTR);

       

        printf("Name: %S \n",pBSTR[0].name);

        printf("SurName: %S \n",pBSTR[0].surname);

        printf("Age: %d \n",pBSTR[0].age);

 

        printf("Name: %S \n",pBSTR[1].name);

        printf("SurName: %S \n",pBSTR[1].surname);

        printf("Age: %d \n",pBSTR[1].age);

 

 

But when you run this application it will give you an exception.

If you debug, you can see that the HRESULT is �-2147319783� which means �Old format or invalid type library.�

 

So LPSTR is not going to work for us.

 

Solution

 

So now how we can solve the issue.

Make your struct look like this

 

[StructLayout(LayoutKind.Sequential)]

public struct MyStruct

{

        [MarshalAs(UnmanagedType.BStr)]

        public string name;

        [MarshalAs(UnmanagedType.BStr)]

        public string surname;

        public int age;

      }

 

Register the dll once again and look at the tlb.

 

 

See that now it is BSTR instead of LPSTR.

 

Now run the C++ Console application

 

 

 

Requirements

 

          In order to run mz test application

1)    Open the C# solution in a VS 2005.

2)    Build the Solution.

3)    Use regasm to register the tlb

4)    Open the C++ dsw in VS 6.

5)    In the #import section, Refer to appropriate location in your machine. �#import "E:\MyTestApps\TestInterOp\Debug\MyInterOp.tlb"�

6)    Run the Console application and that�s it.

posted @ 2009-06-12 14:50  飞扬跋扈  阅读(514)  评论(1编辑  收藏  举报