您好,我正在用 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;
}
但是我得到了错误,返回的内存地址为零。这里有什么问题?请帮助我了解导致问题的原因以及解决方法,谢谢!
最佳答案
为什么 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 = &descriptionList[0];
将通过 won't do anything 编译,即使 *listRef = &descriptionList[0];
以某种方式编译它也不会包含您想要的内容。
所以函数签名应该包含三重指针以允许返回一组字符串。
SCREENCAPTUREDLL_API void getAudioDeviceList(wchar_t*** listRef, int* listSize)
{
...
*listRef = &descriptionList[0];
}
然后您的 PInvoke 将正常工作,因为它将具有指向一组字符串指针的相同指针。
关于c# - 具有指向指针参数的指针的 PInvoke 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41621645/