65.9K
CodeProject 正在变化。 阅读更多。
Home

从 C++ 调用 C# 代码并读取包含字符串的结构数组

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.05/5 (12投票s)

2006年11月2日

CPOL

2分钟阅读

viewsIcon

137302

downloadIcon

5311

如何从 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 测试应用程序。

  1. 在 VS 2005 中打开 C# 解决方案。
  2. 构建解决方案。
  3. 使用 regasm 注册 tlb
  4. 在 VS 6 中打开 C++ dsw
  5. #import 部分,引用您机器上的适当位置。“#import "E:\MyTestApps\TestInterOp\Debug\MyInterOp.tlb"”。
  6. 运行控制台应用程序,就完成了。
© . All rights reserved.