Wednesday, April 01, 2009

BSTR簡介和內部結構

[轉載] BSTR詳解一 - BSTR簡介和內部結構
COM是一種跨編程語言的平台,需要提供語言無關的數據類型。多數編程語言有自己的字符串表示。
  • C++ 字符串是以0結束的ASCIIUnicode字符數組
  • Visual Basic字符串是一個ASCII字符數組加上表示長度的前綴。
  • Java字符串是以0結束的Unicode字符數組。
需要定義一種通用的字符串類型,可以很容易的匹配到不同編程語言。C++中,就是BSTR
2.1 BSTR 簡介
"Basic STRing"的簡稱,微軟在COM/OLE中定義的標準字符串數據類型。對於C++Windows頭文件wtypes.h中定義如下:
typedef wchar_t WCHAR;
typedef WCHAR OLECHAR;
typedef OLECHAR __RPC_FAR *BSTR;;
2.2 BSTR實現
COM中,字符用16-bit OLECHAR表示,這樣使COM可以支持各種code pages,包括Unicode。對於windows系統,可以簡單理解為OLECHAR使用的就是Unicode OLECHAR串與單字節字符串很類似,是一個以null結尾的buffer。唯一的區別是每個字符佔兩個字節,而不是一個
0 1 2 3 4 5 6 7 8 9 0 1
| H | E | L | L | O | \0|
^
OLCHAR
Figure 1. Format of an OLECHAR string.
使用以Null結尾的簡單字符串在COM component間傳遞不太方便。因此,標準BSTR是一個有長度前綴和null結束符的OLECHAR數組。BSTR的前4字節是一個表示字符串長度的前綴。BSTR長度域的值是字符串的字節數,並且不包括0結束符。由於是Unicode串,所以字符數是字節數的一半。這種方式的優點是允許程序員在BSTR串中間嵌入NULL字符。但是,BSTR的前四個字節表示長度,而OLECHAR數組的前四字節表示前兩個字符。這種情況下,對於C++程序,如何實現BSTROLECHAR的交換?答案是COM提供了兩個BSTR分配用的APISysAllocString / SysReallocString。函數返回的指針指向BSTR的第一個字符,而不是BSTR在內存的第一個字節。
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
0a000000 | H | E | L | L | O | \0|
^
BSTR
Figure 2. Format of a BSTR.
下面是SysAllocStringSysFreeString的偽代碼。
BSTR SimpleSysAllocString( const OLECHAR * sz)
{
if ( sz == NULL) return NULL;
BYTE* buf = new BYTE[sizeof(INT32) + (wcslen(sz)+1)*sizeof(OLECHAR) ];
if(buf == NULL)
{
return NULL;
}
else
{
INT32 len = wcslen(sz) * sizeof(OLECHAR);
*((INT32*) buf) = len;
wcscpy( (WCHAR*)(buf+sizeof(INT32)), sz);
return (BSTR)(buf+sizeof(INT32));
}
}
VOID SimpleSysFreeString( BSTR bstr)
{
if(bstr != NULL)
{
BYTE* start = (BYTE*)bstr - sizeof(INT32);
delete []start;
}
}