我正在为某些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个值?数组的长度无关紧要,仅在调用该方法之后才保留第一个值。

提前致谢。任何帮助是极大的赞赏。

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

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, 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);

最佳答案

通过P / Invoke中的ref传递数组是一个奇怪的操作,因为大概它允许被调用函数从本机端替换引用。我不太确定为什么您发布的代码不起作用,因为它似乎是合理的(除了前面提到的带有ref的奇数和 header 中的声明与参数类型不匹配之外)。

但是,我认为您可以通过不传递ref并仅使用指向数组的指针来轻松更改代码以解决此问题。您不是要尝试重新分配数组引用本身;您只关心更改其内容。

10-07 19:28
查看更多