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.