从 C++ 调用 C# 代码并读取包含字符串的结构数组
如何从 C++ 调用 C# 代码并读取包含字符串的结构体数组。
引言
我的 C++ 代码试图读取 C# 中包含字符串数据的结构体数组。令我惊讶的是,我发现只包含整数的结构体数组很容易获取,但如果数组中包含字符串,则需要做更多的事情。我在 Google 上搜索,发现很多人都在讨论同样的问题,并遇到了一个异常,提示“旧格式或无效的类型库”。但我无法找到答案,并且由于我能够自己解决这个问题,因此我在这里发布解决方案。
基本思路
我有一个包含结构体的 C# DLL,假设
public struct MyStruct
{
public string name;
public string surname;
public int age;
}
我有一个接口,如下所示
public interface ITest
{
MyStruct[] GetData
{
get;
}
}
我的主类是
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;
}
}
}
现在构建 DLL。然后,从 Visual Studio 命令提示符中,输入“regasm MyInterOp.dll /tlb:MyInterOp.tlb”。使用 OleViewer 查看 tlb。找到标签 MyStruct
。它将有一个 LPSTR
。
现在在 C++ 中创建一个控制台应用程序,如下所示
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);
当您运行此应用程序时,它会引发一个异常。如果进行调试,您会看到 HRESULT 是“-2147319783”,这意味着“旧格式或无效的类型库”。因此,LPSTR
对我们不起作用。
解决方案
我们如何解决这个问题?让您的结构体看起来像这样
[StructLayout(LayoutKind.Sequential)]
public struct MyStruct
{
[MarshalAs(UnmanagedType.BStr)]
public string name;
[MarshalAs(UnmanagedType.BStr)]
public string surname;
public int age;
}
再次注册 DLL 并查看 tlb。可以看到现在是 BSTR
而不是 LPSTR
。
现在运行 C++ 控制台应用程序。
要求
为了运行 mz 测试应用程序。
- 在 VS 2005 中打开 C# 解决方案。
- 构建解决方案。
- 使用 regasm 注册 tlb。
- 在 VS 6 中打开 C++ dsw。
- 在
#import
部分,引用您机器上的适当位置。“#import "E:\MyTestApps\TestInterOp\Debug\MyInterOp.tlb"
”。 - 运行控制台应用程序,就完成了。