c# - 将 SAFEARRAY 用于 C++ C#

标签 c# c++ interop safearray

我正在尝试从 C++ 中使用用 C# 编写的库。为此,我被告知使用 COM Interop,对此我知之甚少。 我正在尝试以一种方式传递一维数组并返回一维数组,但我的返回数组最终全是零。 为了简化这个论坛的问题,我简化了我的程序:我什至不传递输入数组。

我的 C# 程序是这样的

using System;
using System.Runtime.InteropServices;

namespace FillArray
{
    [ComVisible(true)]
    [Guid("DABAEF7C-D2B8-4769-98C8-1AF211EF7D48")]
    public interface IFillArray
    {
        int fillTheArrayWithSquares(int[] array);
    }

    [ComVisible(true)]
    [Guid("124A66FD-CED3-4a8e-B0F0-BAA88B421E97")]
    public class Class1: IFillArray
    {
        public int fillTheArrayWithSquares(int[] array)
        {
            int len = array.Length;
            int i;
            for (i = 0; i < len; i++)
                array[i] = i * i;

            return len;
        }
    }
}

在同一个解决方案中,我有一个如下所示的 C++ 客户端:

#import "D:\dev\CSharp\FillArray\FillArray\bin\Release\FillArray.tlb" raw_interfaces_only
#include "stdafx.h"
using namespace FillArray;

int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = CoInitialize(NULL);
    long retval;
    IFillArrayPtr pIFillArray(__uuidof(Class1));
    SAFEARRAY *output;
    SAFEARRAYBOUND  BoundOutput;
    BoundOutput.cElements = 10;
    BoundOutput.lLbound = 0;
    output = SafeArrayCreate(VT_I4, 1, &BoundOutput);
    int *p_output_contents;
    HRESULT hrFill  = pIFillArray->fillTheArrayWithSquares( output, &retval);
    HRESULT hrOutput = SafeArrayAccessData(output, (void HUGEP**)&p_output_contents);
    if(SUCCEEDED(hrFill) && SUCCEEDED(hrOutput))
    {

    for(int i = 0; i < 10; i++)
        printf("%d ",p_output_contents[i]);
    printf("\n");
    printf("retval = %d\n",retval);
    SafeArrayUnaccessData(output);// not robust error handling
    SafeArrayDestroy(output);//not robust error handling logic
    }

    CoUninitialize();

    return 0;
}

我已将 C++ 项目配置为使用/clr: oldsyntax,因为我正在改编推荐此方法的旧文章。不幸的是,这在 VS 2008(我正在使用)中似乎已被弃用,我将无法将其移植到 VS2013。 所以我有两个问题: 1) 为什么我的 C++ 应用程序打印 10 个零? 2) 我将如何更新我的语法以避免/clr:oldsyntax。

还有一点:我在一些讨论中看到 C# 数组不对应于 SAFEARRAYS,但类型的选择是 Intellisense 告诉我应该使用的。 谢谢。

最佳答案

首先,VS 中有两种类型的 C++ 项目:

  1. native C++ 项目,默认情况下没有/clr 选项。
  2. C++/CLI 项目,默认带有/clr 选项。 C++/CLI 可以访问 native 和托管世界,因此如果您想使用 C# DLL,只需添加此 DLL 作为引用并直接使用它,在这种情况下不需要 COM。

如果原生C++项目要使用C# DLL,一种方式是通过COM,另一种方式是使用C++CLI项目作为桥梁。

如果使用 COM,则必须处理 SAFEARRAY,这很容易出错。至于您的问题 1,您使用 SAFEARRAY 作为输出参数,这很复杂。我建议您将函数 fillTheArrayWithSquares 的定义更改为:

public int[] fillTheArrayWithSquares( )

所以它会返回一个SAFEARRAY给C++代码,SAFEARRAY的长度已经包含在SAFEARRAY中。

关于c# - 将 SAFEARRAY 用于 C++ C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23085680/

相关文章:

c# - 字典 KeyCollection 奇怪性

c# - Shell32.Folder.GetDetailsOf(..,..) 有哪些可用选项?

c++ - QComboBox如何使用QItemSelectionModel?

memory-management - C++/CLI 资源管理困惑

c# - 如何从 .NET 应用程序使用 WinFax Pro COM 对象?

c# - 为什么 Visual Studio 2010 (Intellisense) 会停止生成接口(interface)指针?

c++ - 继承-初始化问题

c++ - 指向数组困境的指针

c++ - OpenCL/GL 互操作 : write_imagef to shared gltexture is all white (1, 1,1,1)

c# - 关于面向对象和库设计的几个问题