Блок памяти в BSTR и обратно.
От: Бабаев Аркадий Леонидович Россия  
Дата: 20.10.08 15:17
Оценка:
Здравствуйте. BSTR хранит информацию о своей длине, поэтому через BSTR можно передавать строки, в том числе содержание '\0'.
Собственно у меня есть задача, необходимо кучу байтов (CharHeap, там могут быть нулевые символы) переделать в BSTR, а потом обратно.

bstr_t для этих целей не годится. К специальным средствам прибегать я готов, но чем их будет меньше, тем лучше.
Самые хорошие методы (как мне показалось) реализации, я увидел такими, с использованием mbtowc и wctomb:

 void CharHeapToBstr(BSTR* bstr, const char* str, const ULONG len)
{
    wchar_t* wch = new wchar_t[len + 1];

    wch[len] = '\0';
    for (unsigned i = 0; i < len; i++)
        mbtowc(&wch[i], &str[i], 1);

    *bstr = SysAllocStringLen(wch, len);

    delete[](wch);
    return;
}

void BstrToCharHeap(char** str, ULONG* len, const BSTR bstr)
{
    *len = SysStringLen(bstr);//SysStringByteLen(bstr) / 2;
    *str = new char[*len + 1];

    memset(*str, '\0', *len+1);
    for(unsigned i = 0; i<= *len; i++)
        wctomb(&(*str)[i], bstr[i]);
    return;
}


Но при этом уже BstrToCharHeap возвращает пустую строчку. Подскажите пожалуйста, что я не так делаю испольщуя эти функции wctomb, или, если есть более удобный вариант, то его. Перечитал много с форума, ничего не нашел о блоках памяти, тут специфика — это не строки и там может быть любой мусор.

21.10.08 13:15: Перенесено модератором из 'C/C++' — Кодт
С уважением, Аркадий.
bstr charheap
Re: Блок памяти в BSTR и обратно.
От: Юрий Жмеренецкий ICQ 380412032
Дата: 20.10.08 16:30
Оценка:
Здравствуйте, Бабаев Аркадий Леонидович, Вы писали:

БАЛ>Здравствуйте. BSTR хранит информацию о своей длине, поэтому через BSTR можно передавать строки, в том числе содержание '\0'.

БАЛ>Собственно у меня есть задача, необходимо кучу байтов (CharHeap, там могут быть нулевые символы) переделать в BSTR, а потом обратно.

Вообще "The preferred method of passing binary data is to use a SAFEARRAY of VT_UI1, which will not be translated by OLE."
но если очень нужно, то см. SysAllocStringByteLen: "This function is provided to create BSTRs that contain binary data."
Re[2]: Блок памяти в BSTR и обратно.
От: Аркадий Россия  
Дата: 20.10.08 18:10
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Здравствуйте, Бабаев Аркадий Леонидович, Вы писали:


БАЛ>>Здравствуйте. BSTR хранит информацию о своей длине, поэтому через BSTR можно передавать строки, в том числе содержание '\0'.

БАЛ>>Собственно у меня есть задача, необходимо кучу байтов (CharHeap, там могут быть нулевые символы) переделать в BSTR, а потом обратно.

ЮЖ>Вообще "The preferred method of passing binary data is to use a SAFEARRAY of VT_UI1, which will not be translated by OLE."

ЮЖ>но если очень нужно, то см. SysAllocStringByteLen: "This function is provided to create BSTRs that contain binary data."

Это да, а как конвертировать из BSTR в char*?

ЗЫ: про SAFEARRAY of VT_UI1 я как-то упустил, спасибо, что глаза мне открыли, я думал именно BSTRом оно и передается...
С уважением, Аркадий.
Re[3]: Блок памяти в BSTR и обратно.
От: Юрий Жмеренецкий ICQ 380412032
Дата: 20.10.08 19:17
Оценка:
Здравствуйте, Аркадий, Вы писали:

ЮЖ>>Вообще "The preferred method of passing binary data is to use a SAFEARRAY of VT_UI1, which will not be translated by OLE."

ЮЖ>>но если очень нужно, то см. SysAllocStringByteLen: "This function is provided to create BSTRs that contain binary data."

А>Это да, а как конвертировать из BSTR в char*?

Что значит "конвертировать" ? Здесь нужно только преобразовать указатели. SysAllocStringByteLen выделяет буфер на n байт(столько же вернет и SysStringByteLen), сохраняет размер и возвращает указатель на начало буфера как BSTR.

int main()
{
  char data[] = {'1', '2', 0, 0, '3', '4', 0, '5', '6'};
  size_t size = sizeof(data)/sizeof(char);
    
  if(BSTR bstr = ::SysAllocStringByteLen(data, size))
  {
    assert(::SysStringByteLen(bstr) == size);
    char* str = reinterpret_cast<char*>(bstr);
        
    assert(memcmp(str, data, size) == 0); 
    
    ::SysFreeString(bstr);
  }
}
Re: Блок памяти в BSTR и обратно.
От: ioni Россия  
Дата: 21.10.08 04:19
Оценка:
Здравствуйте, Бабаев Аркадий Леонидович, Вы писали:

БАЛ>Собственно у меня есть задача, необходимо кучу байтов (CharHeap, там могут быть нулевые символы) переделать в BSTR, а потом обратно.

А почему вы не хотите обычный пересылкой байт
объявите метод как
 SendBinaryData(long len, byte* data)
и вперед
Re[2]: Блок памяти в BSTR и обратно.
От: Аркадий Россия  
Дата: 21.10.08 09:43
Оценка:
Здравствуйте, ioni, Вы писали:

I>Здравствуйте, Бабаев Аркадий Леонидович, Вы писали:


БАЛ>>Собственно у меня есть задача, необходимо кучу байтов (CharHeap, там могут быть нулевые символы) переделать в BSTR, а потом обратно.

I>А почему вы не хотите обычный пересылкой байт
I>объявите метод как
 SendBinaryData(long len, byte* data)
и вперед


Надо, чтобы это потом теоретически мог воспринять VBA или кто угодно подобный. Как он это будет делать — не моя задача, а вот перекинуть "мусор" я обязан. Ну и, соответственно, прочитать "мусор".
Насколько я понял, методы пересылки байт — только через SAFEARRAY (что рекомендуется) или через BSTR...
С уважением, Аркадий.
Re[4]: Блок памяти в BSTR и обратно.
От: Аркадий Россия  
Дата: 21.10.08 09:44
Оценка:
Здравствуйте, Юрий Жмеренецкий, Вы писали:

ЮЖ>Здравствуйте, Аркадий, Вы писали:


ЮЖ>>>Вообще "The preferred method of passing binary data is to use a SAFEARRAY of VT_UI1, which will not be translated by OLE."

ЮЖ>>>но если очень нужно, то см. SysAllocStringByteLen: "This function is provided to create BSTRs that contain binary data."

А>>Это да, а как конвертировать из BSTR в char*?

ЮЖ>Что значит "конвертировать" ? Здесь нужно только преобразовать указатели. SysAllocStringByteLen выделяет буфер на n байт(столько же вернет и SysStringByteLen), сохраняет размер и возвращает указатель на начало буфера как BSTR.

ЮЖ>
ЮЖ>int main()
ЮЖ>{
ЮЖ>  char data[] = {'1', '2', 0, 0, '3', '4', 0, '5', '6'};
ЮЖ>  size_t size = sizeof(data)/sizeof(char);
    
ЮЖ>  if(BSTR bstr = ::SysAllocStringByteLen(data, size))
ЮЖ>  {
ЮЖ>    assert(::SysStringByteLen(bstr) == size);
ЮЖ>    char* str = reinterpret_cast<char*>(bstr);
        
ЮЖ>    assert(memcmp(str, data, size) == 0); 
    
ЮЖ>    ::SysFreeString(bstr);
ЮЖ>  }
ЮЖ>}
ЮЖ>


Спасибо!! Вот я тупил, как-то считал обязательным перевод даже мусорных байт в wchar... =) Действительно же, так намного проще.
С уважением, Аркадий.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.