简体   繁体   中英

Marshalling C-style array of LPWSTR to managed string[] using pInvoke

I'd like to call an unmanaged method that allocates memory, creates an array of LPWSTR s, and returns it to managed code. I'd like to avoid in/out parameters and writing code to manage memory and variable scopes as much as possible so I decided I would rely on using CoTaskMemAlloc and let the marshaller automagically clean up after me.

Here's what I have (a modified version of ap/invoke tutorial method on MSDN):

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;
}

and on the managed side:

[DllImport("Dll1.Windows.dll", CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, ArraySubType = UnmanagedType.LPWStr)]
public static extern string[] TestArrayOfStrings(out int count);

As you can see I've tried to use additional attributes but the marshaller just doesn't seem to like it--I keep getting "Cannot marshal 'return value': Invalid managed/unmanaged type combination." I am trying to maintain typing as an array of LPWSTR s and would like to avoid SAFEARRAY , for which marshalling is marked obsolete.

Slightly modified code, but the signature was what was important. This method assigns a string value (the third parameter) to the first element of the uninitialized out array passed in.

[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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM