【问题标题】:Pass C# array of object to C++/CLI将 C# 对象数组传递给 C++/CLI
【发布时间】:2016-09-20 16:33:45
【问题描述】:

我不得不在 C# 库中公开一些方法,以便可以从用 C++ (VC++ 6.0) 编写的外部程序中使用它们。因此,我创建了一个混合程序集,到目前为止它工作得很好,但是我在使用返回 .NET 对象数组的方法时遇到了一些问题。

该方法的 .NET 签名是:

public Results[] Measure(String model, String identifier);

Results 本身在哪里:

public class Results
{
    public String[] ElementType;
    public bool[] HasError;
}

为了从 C++ 提供入口点,我开始编写一个 C++/CLI 包装器方法,如下所示:

std::vector<ResultsWrapper> Measure(char* model, char* identifier)
{
    // Call .NET code
    String^ gcmodel = gcnew System::String(model);
    String^ gcidentifier = gcnew System::String(identifier);
    cli::array<Results^>^ gcres = myNetInstance->Measure(gcmodel, gcidentifier);

    // Convert results to C++ vector
    std::vector<ResultsWrapper> ret;
    for (int ki = 0; ki < res->Length; ki++)
    {
        ResultsWrapper r = ResultsWrapper(res[ki]->...., );
        ret.push_back(r);
    }

    return ret;
}

但我必须承认我有点迷茫,这很长时间我没有写过一行 C++ 并且很长时间我没有处理手动内存管理...

创建ResultsWrapper 类的最佳解决方案是什么,这样就不需要从 C++ 端进行内存管理了。也许像下面这样?

class ResultsWrapper
{
   public:
      ResultsWrapper(vector<std::String> elementType, vector<bool> hasError)
      {
         this.ElementType = elementType;
         this.HasError = hasError;
      }

   public:
     vector<std:String> ElementType;
     vector<bool> HasError; 
}

注意:我认为 VC++ 6.0 方面的团队不知道 boost 库或 share_ptr 类型(而且我对它们也不是很了解)。所有 C++ 代码都是非常经典的 C++ 代码风格,甚至没有使用stdlib

【问题讨论】:

  • 我认为你必须先序列化数组然后再反序列化
  • @pho3nix 你是对的。至少如果您忽略所有 C++/CLI 功能并且不知道该语言提供了什么。否则你完全是在做不必要的事情。很棒的编程。
  • 你不能使用 std::vector,编译器太老了。出于同样的原因,内存管理也是一个问题,因此使用 new 分配数组也是不可能的。使用 LocalAlloc() 或 SafeArrayCreate() 到达某个地方。
  • 是的,对于曝光部分忘记 C++ - 您的导出需要坚持标准 C 级函数导出,或者您“一路”(在 .NET 方面很容易)并制作COM 对象... COM 可以追溯到很久以前。并且 COM 支持从 .NET 导出 - 但是:您更需要知道您在 COM 中做什么......
  • 谢谢@TomTom ...是的 COM 是我想到的另一种方式,即使我担心客户对 COM / .tlb 等一无所知... 2016 年仍在使用 VC++ 6.0 :/ .. . 我一直在努力提供一个简单的 .exe,结果存储在文件而不是 API 中,但我不在那些决定如此疯狂/无用/愚蠢/耗时的向后支持的人的论文中;)跨度>

标签: c# c++-cli marshalling mixed-mode


【解决方案1】:

我无法安全/轻松地跨 dll 边界传递 STL 类型,所以我回到旧的 char**,手动分配/解除分配,它就可以工作了...

IJW 只是一段时间...然后我尝试检查何时将异常从 .NET 抛出回调用 C++ 应用程序,然后是 patatra ...需要转换为本机异常...再次无法安全地跨越 dll 边界...

混合模式程序集听起来很吸引人从 .NET 转到本机,但在我的情况下是 IJS 体验...我放弃了,将改用 COM。

【讨论】:

    【解决方案2】:

    在 C++/CLI 中,我开始编写这样的包装器方法:

    不,你没有

    public Results[] Measure(字符串模型,字符串标识符);

    没有相似之处

    std::vector Measure(char* model, char* identifier)

    无。

    在 C++/CLI 参考类中不需要编组。使用 String^ 作为指向字符串的指针(而不是 char*)并使用 array&lt;ResultsWrapper&gt;^ 作为指向托管数组的指针。

    根本不需要使用包装器。将一个类声明为托管引用(ref 类),您可以从 .NET 端调用它,因为它是一个 .NET 类。

    【讨论】:

    • 是的。 C++/CLI 绝对值得 MS 更多的爱 - 文档是神秘的,你会得到 C++ 的所有怪癖,.NET 的怪癖,以及试图将两者混合在一起产生的古怪行为。这是头痛的秘诀。但是你在 RTFM 部分是对的——这个标签中 3/4 的问题是关于字符串编组的:-\
    • @TomTom OP 提出的问题不是“如何使用 C# 中的 C++/CLI 类”,而是“我需要在 C# 库中公开一些方法,以便它们可以从使用 VC++ 6.0 编写的外部程序中使用。”您的回答究竟是如何解决这些问题的?
    猜你喜欢
    • 2022-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-06
    • 2012-08-21
    • 2018-07-29
    • 2015-08-30
    相关资源
    最近更新 更多