Как автоматически конвертировать const wchar_t * из C DLL в C # строку

Это просто любопытство. Возможно, в этом мире есть человек, который делал такие вещи:

Я должен экспортировать функцию C и загрузить ее из кода C # через DllImport

const wchar_t * SysGetLibInfo() {
return dllmanager.SysGetLibInfo();
}

Лучший способ сделать это, и это широко рекомендуется, — объявить IntPtr, а затем преобразовать его в строку, используя некоторую функцию. Другими словами, как-то так

[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SysGetLibInfo();
// ...
Marshal.PtrToStringUni(SysGetLibInfo());

Этот подход работает. Но есть ли способ сделать это автоматически? Чтобы SysGetLibInfo возвращал строку? Я нашел несколько предложений, как это:

[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPWStr)]
private static extern string SysGetLibInfo();

Но это не работает, и, согласно множеству примеров и скудных отчетов, это не должно работать.

Есть ли способ написать свой собственный атрибут, например MarshalAs, который будет конвертировать IntPtr в строку? Что-то похожее на это:

[DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
[return: MyOwnMarshalPtrToStringUni]
private static extern string SysGetLibInfo();

Заранее спасибо за любую информацию или полезные ссылки, примеры, книги. Опять же, это просто любопытство.

Постскриптум Предложение обернуть SysGetLibInfo отдельной функцией, которая преобразует результат в строку, используя PtrToStringUni, не вариант;)

2

Решение

Вы не можете переопределить MarshalAs, но вместо этого вы можете использовать собственный маршаллинг

http://msdn.microsoft.com/en-us/library/w22x2hw6.aspx

  [DllImport(dll, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(MyMarshaller))]
private static extern string SysGetLibInfo();
1

Другие решения

Я думаю, что проблема с PLWStr:

вы не можете использовать значение LPWStr с неуправляемой строкой если только
строка была создана с помощью неуправляемой функции CoTaskMemAlloc

Это отлично работает. Родной код:

// header
extern "C" __declspec(dllexport) wchar_t* SysGetLibInfo(void);

// implementation
extern "C" __declspec(dllexport) wchar_t* SysGetLibInfo(void)
{
return TEXT("Hello from unmanaged world!");
}

Управляемый код:

    [DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPTStr)]
static extern string SysGetLibInfo();

Если вы измените нативную функцию следующим образом:

extern "C" __declspec(dllexport) wchar_t* SysGetLibInfo(void)
{
wchar_t* pStr = (wchar_t*)CoTaskMemAlloc(100);

ZeroMemory(pStr, 100);

wcscpy(pStr, TEXT("Hello from unmanaged world!"));

return pStr;
}

затем [return: MarshalAs(UnmanagedType.LPWStr)] тоже будет работать

1

По вопросам рекламы [email protected]