TCHAR * in говорит мне, что это ввод Unicode (UNICODE определен в CE), но char * говорит мне, что это, скорее всего, байтовый массив (или строка ascii), и кто бы ни создавал этот API, его нужно шлепнуть для смешивания двух, так как это действительно очень плохой дизайн.
Вы, конечно, не можете упорядочить возвращение как строку широких символов, потому что она не одна. На рабочем столе вы бы использовали предложение Тони, но MSDN (и практика) ясно показывает , что он недоступен в CF (не знаю, почему MS думала, что нам это не понадобится).
Smart Device Framework имеет его . Другой вариант - использовать Marshal для копирования из возвращенного указателя в байтовый массив, а затем использовать Encoding.ASCII, чтобы превратить этот массив в строку. Конечно, это указывает на еще один очевидный недостаток этого API, заключающийся в том, что он не должен возвращать строку .
РЕДАКТИРОВАТЬ 1
Поскольку я вижу другие предложения относительно того, что вы должны делать, с которыми я не совсем согласен, я полагаю, что должен привести вам пример:
Ваш родной вызов должен выглядеть примерно так:
extern "C"
__declspec(dllexport)
const BOOL __cdecl Connect(TCHAR* lpPostData,
TCHAR *returnBuffer,
DWORD *returnSize)
{
// validate returnSize, returnBuffer, etc
// write your data into returnBuffer
TCHAR *data = _T("this is my data");
_tcscpy(returnBuffer, data);
*returnSize = (_tcslen(data) + 1) * sizeof(TCHAR);
return succeeded;
}
Обратите внимание, что я просто возвращаю код успеха. Текстовые данные передаются в виде указателя вместе с длиной для него (поэтому API знает, сколько места он может использовать, и может возвращать, сколько он использовал). Также не то, чтобы я соответствовал моим типам данных строковых переменных, и я использую макросы TCHAR, которые в CE станут wchar_t, что согласуется с остальной частью ОС (у которой почти нет API-интерфейсов ASCII для начала).
Большая часть набора API WIn32 работает точно так же.
Ваша декларация P / Invoke очень проста:
[DllImport("test.dll", SetLastError=true)]
private static extern bool Connect(string postData,
StringBuilder data,
ref int length);
Использовать его также просто:
void Foo()
{
int length = 260;
StringBuilder sb = new StringBuilder(length);
if(Connect("Bar", sb, ref length))
{
// do something useful
}
}
Обратите внимание, что StringBuilder должен быть инициализирован до некоторого размера, и этот размер - то, что вы передаете в третьем параметре.