【问题标题】:PInvoke function with pointer to pointer parameter带有指向指针参数的指针的 PInvoke 函数
【发布时间】:2017-01-12 19:43:39
【问题描述】:

您好,我正在用 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;
    }

但是我得到了错误,返回的内存地址为零。这里有什么问题?请帮助我了解问题的原因以及解决方法,谢谢!

【问题讨论】:

    标签: c# c++ pointers reference porting


    【解决方案1】:

    为什么 Pinvoke 不起作用?因为您试图将指向字符串的指针解释为指向一组字符串的指针。但是 PInvoke 并没有什么问题——它的发生是因为新函数签名及其内部代码实际上存在问题。

    见:

    SCREENCAPTUREDLL_API void getAudioDeviceList(wchar_t** listRef, int* listSize);
    

    无法提供与

    相同的数据
    DLL_API wchar_t** getAudioDeviceList(int* listSize)
    

    因为原始定义基本上返回了指向一组字符串指针的指针(我的意思是 C 风格的字符串),而 wchar_t** listRef can only 允许返回一个指向字符串的指针。

    SCREENCAPTUREDLL_API void getAudioDeviceList(wchar_t** listRef, int* listSize)
    {
         ...
         *listRef = "string";
    

    我不知道新版本的函数内部发生了什么(你没有显示代码),但listRef = &amp;descriptionList[0]; 将通过won't do anything 编译,即使*listRef = &amp;descriptionList[0]; 以某种方式编译它也不会包含你想要的。

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

    SCREENCAPTUREDLL_API void getAudioDeviceList(wchar_t*** listRef, int* listSize)
    {
        ...
        *listRef = &descriptionList[0];
    }
    

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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-11
    • 1970-01-01
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    • 2014-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多