PInvoke函数,指针指针参数

时间:2017-01-12 19:43:40

标签: c# c++ pointers reference porting

您好我用C#包装C ++库。 C ++中的下一个函数:

    SCREENCAPTUREDLL_API wchar_t** getAudioDeviceList(int* listSize) {
        static std::vector<wchar_t*> descriptionList;
        AudioCaptureList::getInstance().Update();
        AudioCaptureList::getInstance().getList(&descriptionList);

        *listSize = descriptionList.size();
        return &descriptionList[0];
    }

包装下一个C#代码:

    [DllImport(screenCaptureDLLPath, CallingConvention = callConversion)]
    private static extern IntPtr getAudioDeviceList(ref int arrayCount);

    public static string[] GetAudioDeviceList()
    {
        IntPtr outputStr;
        int length = 0;

        outputStr = getAudioDeviceList(ref length);
        string[] resultArray = new string[length];
        for (int j = 0; j < length; j++)
        {
            resultArray[j] = Marshal.PtrToStringUni(Marshal.ReadIntPtr(outputStr, 4 * j));
        }

        return resultArray;
    }

完美无缺,完全符合我的预期,但我正要改变我从函数本身返回值到引用变量的方式,所以我将代码更改为:

C ++

    SCREENCAPTUREDLL_API void getAudioDeviceList(wchar_t** list, int* listSize) {
        static std::vector<wchar_t*> descriptionList;
        AudioCaptureList::getInstance().Update();
        AudioCaptureList::getInstance().getList(&descriptionList);

        *listSize = descriptionList.size();
        list = &descriptionList[0];
    }

C#

    [DllImport(screenCaptureDLLPath, CallingConvention = callConversion)]
    private static extern void getAudioDeviceList(out IntPtr listRef, ref int arrayCount);

    public static string[] GetAudioDeviceList()
    {
        IntPtr outputStr;
        int length = 0;

        getAudioDeviceList(out outputStr, ref length);
        string[] resultArray = new string[length];
        for (int j = 0; j < length; j++)
        {
            resultArray[j] = Marshal.PtrToStringUni(Marshal.ReadIntPtr(outputStr, 4 * j));
        }

        return resultArray;
    }

但我收到错误,返回的内存地址为零。这里有什么问题?请帮助我理解导致问题的原因以及如何解决问题,谢谢!

1 个答案:

答案 0 :(得分:1)

为什么Pinvoke没有工作?因为您试图将指向字符串的指针解释为指向一组字符串的指针。但是PInvoke没有任何问题 - 因为实际上新函数签名及其内部代码存在问题。

见:

connectedGroups

无法提供与

相同的数据
SCREENCAPTUREDLL_API void getAudioDeviceList(wchar_t** listRef, int* listSize);

因为原始定义基本上返回指向一组指向字符串的指针(C样式字符串,我的意思),而DLL_API wchar_t** getAudioDeviceList(int* listSize) can only允许返回指向字符串的单个指针。

wchar_t** listRef

我不知道新版本的函数内容是什么(您没有显示代码),但SCREENCAPTUREDLL_API void getAudioDeviceList(wchar_t** listRef, int* listSize) { ... *listRef = "string"; 将编译won't do anything,即使listRef = &descriptionList[0];以某种方式编译它不会包含你想要的东西。

因此,函数签名应包含三重指针,以允许返回一组字符串。

*listRef = &descriptionList[0];

然后你的PInvoke将正常工作,因为它将具有指向一组字符串指针的相同指针。