Скрытая строка для LPVOID и LPCWSTR в C++

Я работаю с winHTTP API на С++ и начал писать класс-оболочку для своего приложения. Для простоты у меня есть ряд функций, которые могут принимать строковые параметры и использовать их в вызовах winHTTP. Однако многие из них требуют, чтобы данные были LPVOID или LPCWSTR. Я могу заставить все это работать, заставив мои функции-оболочки принимать параметры LPVOID или LPCWSTR, но я бы предпочел строковые параметры. Так есть ли способ спрятаться от жала до LPVOID/ LPCWSTR?

Мои попытки (ниже) только что привели к тарабарщине

bool httpWrapper::setPostData(const string &postData){

 _postData = (LPVOID)postData.c_str();

 _postData_len = 47;

 return false;
}

Любая помощь приветствуется

Спасибо


person Andy    schedule 06.02.2010    source источник


Ответы (4)


Использовать это:

bool httpWrapper::setPostData(const string &postData){ 

 _postData = (LPWSTR)postData.c_str(); 

 _postData_len = 47; // Something else, actually.

 return false; 
}

LPWSTR _postData;

Вы можете передать LPWSTR методам, которые ожидают LPCWSTR. Таким образом, вы можете работать со строками.

Кстати, вы только что пытались передать строку? Я ожидаю, что это тоже сработает, и это лучше, чем получение LPWSTR.

Итак, в этом случае это будет выглядеть так:

bool httpWrapper::setPostData(const string &postData){ 

 _postData = postData; 

 _postData_len = 47; // Whatever.

 return false; 
}
string _postData;
person Community    schedule 06.02.2010

Будьте осторожны с поведением c_str(). Возвращаемый char* является временным, он станет недействительным после изменения или уничтожения строки. Это вполне может произойти до того, как будет использован _postData, возможно, сразу после возврата setPostData(). Вам нужно будет скопировать его.

Следующая проблема заключается в том, что c_str() возвращает не LPCWSTR, а LPCSTR. Приведение не может преобразовать его, что производит китайский язык. Вам нужно будет преобразовать его в строку Unicode, например, с помощью MultiByteToWideChar().

person Hans Passant    schedule 06.02.2010

Конечно, есть способ преобразовать вашу строку во что-то, вы можете взять адрес и передать его как LPCWSTR или как LPVOID (это может быть другое дело в случае LPVOID).

Теперь внимательно прочитайте приведенное выше утверждение.

Чтобы знать, что делать, сначала вы должны знать, что такое LPCWSTR и LPVOID. У меня странное предчувствие, что это могут быть какие-то указатели. MSDN может помочь. Попробуйте, например, здесь

Затем вы должны знать, что функция, которой вы передаете эти параметры, будет делать с памятью, на которую указывают эти указатели. Будет ли он просто читать его или, может быть, изменить его? И как это интерпретировать в случае LPVOID.

Я не могу помочь вам с LPVOID, потому что я не знаю API, но LPCWSTR предлагает вам создать строку wide с завершающим нулем, которая будет просто прочитана. Как насчет создания wstring и использования его метода c_str()?

person Maciej Hehl    schedule 06.02.2010

LPVOID — это просто void*, поэтому вы можете преобразовать в него любой указатель, поскольку любой указатель может быть преобразован в void*. Однако это не гарантирует, что эта операция даст правильный результат с точки зрения ваших ожиданий.

Просто LPVOID используется в ситуациях по следующей схеме

int i = 10; // some real data
int* pi = &i; // pointer to data

// convert to opaque pointer, not usable (readable), onlly can be passed around
// for instance to thread procedure
void* pv = pi;

pi = reinterpret_cast<int*>(pv); // convert back to pointer to data
int j = *pi; // access real data

Проблема в том, что вы должны гарантировать, что i будет оставаться в живых, по крайней мере, до тех пор, пока данные будут доступны/используются через указатель pv. Вы должны учитывать, если ваш w

Итак, вы можете сделать это:

bool httpWrapper::setPostData(const string &postData){ 

 _postData = reinterpret_cast<LPVOID>(postData.c_str()); 
 return false; 
}

но вы должны гарантировать, что строковый объект, который вы передаете по ссылке как postData, останется живым, по крайней мере, до тех пор, пока на него указывает _postData. На самом деле _postData указывает на внутреннее расположение возвращенного c_str()

Кроме того, кажется, что вы собираетесь использовать значение, возвращаемое c_str(), как LPWSTR. Чтобы использовать LPWSTR, вам необходимо преобразовать ANSI в широкие символы, например, используя MultiByteToWideChar.

Другими словами, преобразование одного указателя в другой само по себе не является проблемой. Проблема заключается в том, чтобы гарантировать надлежащее время жизни и использования объектов.

person mloskot    schedule 06.02.2010