我想调用一个非托管方法来分配内存,创建一个LPWSTR
数组,并将其返回给托管代码。我想避免输入/输出参数和编写代码来尽可能地管理内存和变量范围,所以我决定依赖于使用CoTaskMemAlloc
并让marshaller在我之后自动清理。
这就是我所拥有的(MSDN上的p / invoke教程方法的修改版本):
extern "C" DLL1_API LPWSTR *TestArrayOfStrings(_In_ int count)
{
STRSAFE_LPWSTR temp = NULL;
wchar_t * ppStrArray[10] = { NULL };
const size_t alloc_size = sizeof(wchar_t *) * 10;
for (int i = 0; i < 10; i++)
{
temp = (STRSAFE_LPWSTR)CoTaskMemAlloc(alloc_size);
if (i % 2 == 0)
StringCchCopy(temp, alloc_size, L"0123456789");
else
StringCchCopy(temp, alloc_size, L"9876543210");
CoTaskMemFree(ppStrArray[i]);
ppStrArray[i] = temp;
}
count = 10;
return ppStrArray;
}
并在管理方面:
[DllImport("Dll1.Windows.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, ArraySubType = UnmanagedType.LPWStr)]
public static extern string[] TestArrayOfStrings(out int count);
正如你所看到的,我已经尝试使用其他属性但是marshaller似乎并不喜欢它 - 我一直得到“无法编组'返回值':无效的托管/非托管类型组合。”我正在尝试将键入作为LPWSTR
的数组进行维护,并希望避免使用SAFEARRAY
,因为编组已被标记为过时。
答案 0 :(得分:0)
稍微修改过的代码,但签名才是重要的。此方法将字符串值(第三个参数)分配给传入的未初始化的数组的第一个元素。
[DllImport("Dll1.Windows.dll", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
public static extern void TestArrayOfStrings(
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] [Out] out string[] test,
out int size, string someString);
extern "C" DLL1_API void TestArrayOfStrings(wchar_t ***strings, int *size, wchar_t *someString){
const size_t alloc_size = 64;
STRSAFE_LPWSTR temp = (STRSAFE_LPWSTR)CoTaskMemAlloc(alloc_size);
StringCchCopy(temp, alloc_size, someString);
*strings = (wchar_t **)CoTaskMemAlloc(sizeof(wchar_t));
*strings[0] = temp;
*size = 1;
}