通过ref将C#数组传递给C ++ DLLImport方法修剪值

时间:2014-07-03 23:05:31

标签: c# c++ arrays dll dllimport

我正在为一些C ++代码制作一个DLL包装器并遇到了一个问题。在提供一些示例代码后,我会更容易地解释我的问题。

在我的C ++应用程序的.h文件中:

#pragma once
namespace Wrapper {
extern __declspec(dllexport)
    void SANDBOX(int arrayLength, int* intArray);
}

在我的C ++应用程序的.cpp文件中:

#include "stdafx.h"
#include "Wrapper.h"
#include <windows.h>
using namespace Wrapper;

extern "C"{

    BOOL APIENTRY DllMain( 
                            HANDLE hModule,
                            DWORD  ul_reason_for_call,
                            LPVOID lpReserved )
    {
        return TRUE;
    } 
    __declspec(dllexport) void SANDBOX(int* arrayLength, int* intArray[])
    {
        if(*intArray == NULL)
        {
            *arrayLength = 5;
            return;
        }
        else
        {
            int i = 0;
            for(i = 0; i < (*arrayLength); i++)
            {
                (*intArray)[i] = 1 + i*i;
            }
        }
    }
}

我的C#应用​​程序会像这样导入方法:

    const string dllFileLocation = "Wrapper.dll";

    [DllImport(dllFileLocation, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public extern static void SANDBOX(ref int arrayLength, ref int[] intArray);

最后,我的C#应用​​程序以如下形式调用代码:

        //Initialize some things
        string outString;
        int numInArray = -1;
        int[] iArray = null;
        //Fill the numInArray integer
        Wrapper_Handle.SANDBOX(ref numInArray, ref iArray);

        //Lets initialize the array and print the values
        iArray = new int[numInArray];
        outString = "";
        foreach(int i in iArray)
        {
            outString += i + "\n";
        }
        MessageBox.Show(outString);

        //Now lets put values into the array and print the new ones out
        Wrapper_Handle.SANDBOX(ref numInArray, ref iArray);
        outString = "";
        foreach(int i in iArray)
        {
            outString += i + "\n";
        }
        MessageBox.Show(outString);

所以,我期望发生的是我创建一个空数组来获取要初始化的值的数量。所以我得到5个,制作一个新的阵列,并打印出来。它得到了我所期望的:一个带有0次的消息框。但是,在再次调用该方法后,第二个消息框只是数字1,没有其他值。看起来其他4个值都是从数组中“切除”的,而C#应用程序再也看不到它们了。

我已成功从C ++ .DLL导入了许多其他函数。它的这个数组符号引起了问题。在调试.DLL时,这些值会正确传递给C ++代码,然后分配它们。

有谁知道为什么C#应用程序“失去”其他4个值?数组的长度无关紧要,只有在调用方法后才保留第一个值。

提前致谢。非常感谢任何帮助。


EDIT-- 在对这个问题的评论中提供了我的问题的解决方案。我在下面发布我的更改:

C ++ .h文件:

#pragma once
namespace Wrapper {
extern __declspec(dllexport)
    void SANDBOX(int arrayLength, int* intArray);
}

C ++ .cpp文件:

#include "stdafx.h"
#include "Wrapper.h"
#include <windows.h>
using namespace Wrapper;

extern "C"{

    BOOL APIENTRY DllMain( 
                            HANDLE hModule,
                            DWORD  ul_reason_for_call,
                            LPVOID lpReserved )
    {
        return TRUE;
    } 
    __declspec(dllexport) void SANDBOX(int* arrayLength, int* intArray)
    {
        if(intArray == NULL)
        {
            *arrayLength = 5;
            return;
        }
        else
        {
            int i = 0;
            for(i = 0; i < (*arrayLength); i++)
            {
                (intArray)[i] = 1 + i*i;
            }
        }
    }
}

C#import:

    const string dllFileLocation = "Wrapper.dll";

    [DllImport(dllFileLocation, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
    public extern static void SANDBOX(ref int arrayLength, int[] intArray);

C#来电:

        string outString;
        int numInArray = -1;
        int[] iArray = null;

        Wrapper_Handle.SANDBOX(ref numInArray, iArray);
        iArray = new int[numInArray];       

        outString = "";
        foreach(int i in iArray)
        {
            outString += i + "\n";
        }


        MessageBox.Show(outString);
        Wrapper_Handle.SANDBOX(ref numInArray, iArray);
        outString = "";
        foreach(int i in iArray)
        {
            outString += i + "\n";
        }
        MessageBox.Show(outString);

1 个答案:

答案 0 :(得分:2)

在P / Invoke中通过ref传递数组是一个奇怪的操作,因为可能它允许被调用的函数替换来自本机端的引用。我不完全确定为什么你发布的代码不起作用,因为它似乎是合理的(除了前面提到的ref与你的标题中的声明并不匹配参数类型)。

但是,我认为您可以轻松更改代码以解决问题,方法是不通过ref传递并只是指向数组。你不是要重新分配数组引用本身;你只关心改变它的内容。