【问题标题】:Marshaling C++ int* to C#将 C++ int* 编组为 C#
【发布时间】:2010-12-06 04:15:40
【问题描述】:

我正在尝试让 dll 工作。

DLL 是用 C++ 编写的,它需要将 int* 传递给 C#。我花了几天的时间来让它工作,但它失败了。我开始拔头发,因为我不知道出了什么问题。我已经尝试了一切。我对 C++ 不像对 C# 那样熟悉,所以问题可能来自那里......

从 dll 中读取正常,但返回的值不正确。我删除了输入,我只是想通过一个测试数组。我在 C++ 中使用的函数是:

extern "C" EAGLE128DLL_API int* encryptFunc()
{
    //return encrypt(x, Q);

    int t[128];

    for(int i = 0; i < 128; i++)
    {
        t[i] = 5;
    }

    return t;
};

我用来调用这个函数的C#代码如下:

[DllImport("C:\\Users\\Leon\\Documents\\Visual Studio 2010\\Projects\\Eagle128DLL\\Release\\Eagle128DLL.dll")]
            public static extern IntPtr encryptFunc();
    ...

IntPtr outputPtr = encryptFunc();
int[] output = new int[128];

Marshal.Copy(outputPtr, output, 0, 128);

输出数组中的值应该全是 5。但我得到的是: 16187392、16190224..etc(不是 5 的)

【问题讨论】:

  • 您还应该能够使用 [return: MarshalAs] 属性返回 int[] 而不是 IntPtr 并让编组器为您完成工作: [return: MarshalAs(UnmanagedType.LPArray , SizeConst = 128)] public static extern int[] encryptFunc();

标签: c# c++ marshalling


【解决方案1】:

C++ 代码包含一个错误:您正在返回一个指向存储在堆栈中的变量的指针(t[128] 只是一个临时变量),这将不起作用。只要您的 encryptFunc 返回,call stack will be unwound 和变量 t[128] 就会被丢弃。

如果您的代码不需要可重入或线程安全,您可以简单地将t[128] 设为静态:

static int t[128];
...
return t;

静态变量将不再存储在堆栈中,并将在函数结束后继续存在。

【讨论】:

  • 哈哈简直不敢相信这么简单。最大的拔毛器总是如此简单,以至于一个人都不会想到它......非常感谢!
  • 我猜我应该在静态数组上使用 delete[] 来将它们从内存中删除?
  • 不,不要那样做。仅在已在堆上分配的内存上使用 delete[](使用 new)。您应该不需要删除静态变量。
【解决方案2】:

我认为您的问题是您试图返回一个已在 C 函数的堆栈上本地声明的值。

最好的办法是将一个预先分配的数组传递给您的 C 函数,该函数将接收该函数创建的数据并将其返回给调用者。

【讨论】:

    猜你喜欢
    • 2011-04-16
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-01
    • 2014-05-18
    相关资源
    最近更新 更多