У меня есть этот код, который использует макрос USE_CONVERSION в проекте C++...
Я задавался вопросом, записано ли это хорошо, (не записанный мной), и если существуют любые лучшие способы сделать это без USES_CONVERSION и макросов W2A.
STDMETHODIMP CInterpreter::GetStringVar(BSTR bstrNamespace, BSTR bstrVar, BSTR *pbstrValue)
{
USES_CONVERSION;
try
{
if (!pbstrValue) return E_POINTER;
char* pszNamespace= W2A(_bstr_t(bstrNamespace).operator wchar_t*());
char* pszVar= W2A(_bstr_t(bstrVar).operator wchar_t*()); // Is this not better done another way????
char pszErrStr[kPYTHONERRBUFSIZE];
char pszStrValue[kPYTHONSTRVALUESIZE];
BOOL bResult= Python_GetStringVar(pszNamespace, pszVar, pszErrStr, pszStrValue, kPYTHONSTRVALUESIZE);
*pbstrValue= _bstr_t(pszStrValue).operator BSTR();
if (!bResult)
throw x::internal_error(A2W(pszErrStr));
return S_OK;
}
}
Есть основанный на классах ATL::CA2W и друзья (в atlconv.h, я полагаю), которые не кладут строку в стек и не используют макросы. Вам не нужна USES_CONVERSION в функции:
throw x::internal_error(ATL::CA2W(pszErrStr));
Также, поскольку ваши аргументы являются BSTR (wchar_t *), вам не нужно преобразовывать их в _bstr_t.
ПРИМЕЧАНИЕ: Время жизни преобразованной строки - это время жизни объекта CW2A, поэтому вам нужно поместить ее в класс string, например:
CStringA arg = CW2A(bstrArg);
ПРИМЕЧАНИЕ 2: pbstrValue - это выходное значение. Экземпляр _bstr_t уничтожит память, выделенную для BSTR. Поэтому нужно либо использовать SysAllocString напрямую, либо отсоединить BSTR:
pbstrValue = SysAllocString(CA2W(retval));
или:
pbstrValue = CComBSTR(CA2W(retval)). Detach();
ПРИМЕЧАНИЕ 3: Явное использование операторов преобразования (.operator BSTR()
) не требуется - компилятор вызовет нужный за вас.
ПРИМЕЧАНИЕ 4: Поскольку это похоже на вызов COM, вы не хотите бросать исключение C++. Вы, вероятно, хотите установить объект IErrorInfo (возможно, с помощником):
if (!bResult) { SetError(CA2W(errorStr)); return E_FAIL; }