【问题标题】:trying to use clr dll but cannot call method from c#尝试使用 clr dll 但无法从 c# 调用方法
【发布时间】:2014-04-17 08:19:44
【问题描述】:

我有一个试图从 c# 访问的 c 函数库。我已经尝试过 PInvoke 路由,但是有包含可变长度数组的结构,所以这种方法不起作用,我被建议尝试 c++/cli。在研究了它(并提出了更多问题)之后,我为我的一个 c 函数创建了一个包装类。 c 函数的输入是一个结构,它包含两个双精度数组和一个数组的长度(另一个是固定大小),以及一个双精度数组。我能够为我的包装器创建一个小测试应用程序(clr 控制台),所以我知道它调用了 c 代码并做了它应该做的事情,我现在只需要弄清楚如何从 c# 调用它。由于它现在是一个托管 dll,因此我已将其添加到我的引用中,我可以将其放入代码中,但方法签名已将数组转换为我无法在 c# 中执行的指针。我尝试只使用 ref 对数组进行 apssing,但无法弄清楚如何使其工作。

c++ 签名:

static void test_wrapper(double prefix[], double arr[], int arrayLength, double value);

所以当我在 c# 中调用它时:

Test_Wrapper_Class.test_wrapper(???, ???, array.Length, 2.2);

然而 ???正在显示它期待一个双 *,我不太确定为此投入什么。

对于奖励积分,我想返回一个双精度数组,但不确定采用哪种方式。对此的选择是:

  1. 只需重复使用 arr,因为返回的数组大小相同
  2. 在输入中添加另一个 double[] 并填充那个
  3. 返回一个双精度[]

【问题讨论】:

    标签: c# c++-cli clr


    【解决方案1】:

    目前还不清楚为什么 C# 难以使用您的函数。请记住,C++/CLI 语言允许您使用托管或非托管数组。您现在使用非托管数组作为参数,因此 C# 代码很难调用该函数。使用不安全的代码并非不可能:

        static unsafe void Main(string[] args) {      // NOTE unsafe keyword
            var arg1 = new double[] { 1, 2, 3 };
            var arg2 = new double[] { 4, 5, 6 };
            fixed (double* arg1ptr = arg1)
            fixed (double* arg2ptr = arg2) {
                Test_Wrapper_Class.test_wrapper(arg1ptr, arg2ptr, arg1.Length, 42.0);
            }
        }
    

    注意 C# 代码需要如何使用 unsafe 关键字。以及它是如何真正不安全的,您没有包含说明第二个数组有多长的参数,因此本机代码可以轻松地写入 GC 堆并破坏它。

    但当您将参数声明为托管数组时,这不是必需的:

    static void test_wrapper(array<double>^ prefix, array<double>^ arr, double value);
    

    安全且易于从 C# 调用。请注意您不再需要传递数组长度参数,您已经从前缀->长度知道它。如有必要,您可以在 C++/CLI 代码中使用 pin_ptr<> 来获得本机代码可以使用的 double*。小心,它只是暂时固定的。

    【讨论】:

    • 太棒了!我现在可以看到它在 Intellisense 中寻找的数组。为建议喝彩。但是在运行时我得到一个 BadImageFormatException。我所有的 dll 都被编译为 64 位,所以不知道为什么会这样?
    猜你喜欢
    • 1970-01-01
    • 2016-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-29
    • 1970-01-01
    • 1970-01-01
    • 2010-12-17
    相关资源
    最近更新 更多