📄 csdn_文档中心_understanding strings in com.htm
字号:
<P style="MARGIN: 0in 0in 0pt">The original Microsoft engineers who
designed COM made a pretty courageous decision: They de facto
imposed Unicode to everyone in the 32-bit world at a time when the
original version of Windows NT was barely taking shape and the
doubled amount of RAM required to hold the same strings could easily
become problematic due to the high cost of memory. But the decision
proved advantageous, as it saved COM developers from having to
implement two variants of each interface (and relative coclasses
implementing it) just to deal with every possible type of client.
</P>
<P style="MARGIN: 0in 0in 0pt">Now we have seen how to define a
COM-compliant character and by extension a COM-compliant string, but
we have not revealed yet how one can initialize such a string with a
string literal. The following statement: </P>
<TABLE border=0 cellPadding=0 cellSpacing=3
style="WIDTH: 100%; mso-cellspacing: 1.5pt; mso-padding-alt: 3.75pt 3.75pt 3.75pt 3.75pt"
width="100%">
<TBODY>
<TR>
<TD
style="BACKGROUND: #dfdfdf; PADDING-BOTTOM: 3.75pt; PADDING-LEFT: 3.75pt; PADDING-RIGHT: 3.75pt; PADDING-TOP: 3.75pt"><PRE>const OLECHAR* pComStr;</PRE><PRE>pComStr = "I love VCDJ and COM";</PRE></TD></TR></TBODY></TABLE>
<P style="MARGIN: 0in 0in 0pt">does work in Windows 3.1x because
only ANSI strings exist there, but will fail to compile on Win32 and
Solaris because we are trying to copy an ANSI string to a Unicode
array of characters. The following form: </P>
<TABLE border=0 cellPadding=0 cellSpacing=3
style="WIDTH: 100%; mso-cellspacing: 1.5pt; mso-padding-alt: 3.75pt 3.75pt 3.75pt 3.75pt"
width="100%">
<TBODY>
<TR>
<TD
style="BACKGROUND: #dfdfdf; PADDING-BOTTOM: 3.75pt; PADDING-LEFT: 3.75pt; PADDING-RIGHT: 3.75pt; PADDING-TOP: 3.75pt"><PRE>const OLECHAR* pComStr;</PRE><PRE>pComStr = L"I love VCDJ and COM";</PRE></TD></TR></TBODY></TABLE>
<P style="MARGIN: 0in 0in 0pt">will give the exact opposite results:
working on Win32, incorrect on Windows 3.1. What we really need is a
way to define the type of a string irrespective of the platform.
Nothing could fit the bill better than a macro, as in the code
below: </P>
<TABLE border=0 cellPadding=0 cellSpacing=3
style="WIDTH: 100%; mso-cellspacing: 1.5pt; mso-padding-alt: 3.75pt 3.75pt 3.75pt 3.75pt"
width="100%">
<TBODY>
<TR>
<TD
style="BACKGROUND: #dfdfdf; PADDING-BOTTOM: 3.75pt; PADDING-LEFT: 3.75pt; PADDING-RIGHT: 3.75pt; PADDING-TOP: 3.75pt"><PRE>const OLECHAR* pComStr;</PRE><PRE>pComStr = OLESTR("I love VCDJ and COM");</PRE></TD></TR></TBODY></TABLE>
<P style="MARGIN: 0in 0in 0pt">The <I>OLESTR()</I> macro is
translated differently depending on the target of the build process,
so we obtain the correct definition in all cases. Wtypes.h reports
it as follows, with some secondary adjustments made to clarify the
original code: </P>
<TABLE border=0 cellPadding=0 cellSpacing=3
style="WIDTH: 100%; mso-cellspacing: 1.5pt; mso-padding-alt: 3.75pt 3.75pt 3.75pt 3.75pt"
width="100%">
<TBODY>
<TR>
<TD
style="BACKGROUND: #dfdfdf; PADDING-BOTTOM: 3.75pt; PADDING-LEFT: 3.75pt; PADDING-RIGHT: 3.75pt; PADDING-TOP: 3.75pt"><PRE>#if defined(_WIN32) && !defined(OLE2ANSI)</PRE><PRE>#define OLESTR(str) L##str</PRE><PRE>#else</PRE><PRE>#define OLESTR(str) str</PRE><PRE>#endif</PRE></TD></TR></TBODY></TABLE>
<P class=MsoNormal><SPAN
style="DISPLAY: none; FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-hide: all"> <o:p></o:p></SPAN></P>
<TABLE border=0 cellPadding=0 cellSpacing=3
style="WIDTH: 100%; mso-cellspacing: 1.5pt; mso-padding-alt: 3.75pt 3.75pt 3.75pt 3.75pt"
width="100%">
<TBODY>
<TR>
<TD
style="BACKGROUND: #dfdfdf; PADDING-BOTTOM: 3.75pt; PADDING-LEFT: 3.75pt; PADDING-RIGHT: 3.75pt; PADDING-TOP: 3.75pt">
<P class=MsoNormal><I><SPAN
style="FONT-FAMILY: Arial; FONT-SIZE: 9pt">Note: In all other
Win32 API implementations there is a discrepancy between
Windows 95 / Windows 98 and Windows NT's string treatment,
since the former employs one-byte ANSI characters and the
latter internally works only with two-byte Unicode characters.
However, when it comes to COM, both operating systems agree on
the use of Unicode strings. </SPAN></I><SPAN
style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 9pt"><o:p></o:p></SPAN></P></TD></TR></TBODY></TABLE>
<P style="MARGIN: 0in 0in 0pt">At this point you may be curious as
to why the data type was called OLECHAR rather than the more obvious
COMCHAR. The answer to this question has its roots partly in history
and partly in marketing: until a few years ago OLE2, the main family
of technologies relying on the COM foundation, was deemed more
important than COM itself, hence the acronym OLE spread everywhere.
The later change of marketing orientation could not be reflected in
the symbol names to avoid breaking a lot of existing and correctly
functioning COM/OLE code. (See my Q&A column in VCDJ print and
online for extensive info on this sometimes unclear transition of
terms and intents.) </P>
<P style="MARGIN: 0in 0in 0pt">OLECHARs are the standard way to
create strings in COM code and by far the most comfortable as long
as C and C++ are used in both the client side and the server side.
Other languages and tools bring their burden of special constraints
that open the way to another kind of string, which constitute the
topic of the next paragraph. </P>
<P align=right style="MARGIN: 0in 0in 0pt; TEXT-ALIGN: right"><B><A
href="http://www.devx.com/free/mgznarch/vcdj/1998/dec98/comstring2.asp"><FONT
color=#990033>continued...</FONT></A></B></P>
<DIV align=center>
<TABLE border=0 cellPadding=0 cellSpacing=3
style="mso-cellspacing: 1.5pt">
<TBODY>
<TR>
<TD
style="PADDING-BOTTOM: 0.75pt; PADDING-LEFT: 0.75pt; PADDING-RIGHT: 0.75pt; PADDING-TOP: 0.75pt">
<P align=center class=MsoNormal
style="TEXT-ALIGN: center"><SPAN
style="FONT-FAMILY: Arial; FONT-SIZE: 9pt">Copyright © 1999 -
Visual C++ Developers Journal<SPAN
style="COLOR: black"><o:p></o:p></SPAN></SPAN></P></TD></TR></TBODY></TABLE></DIV>
<P class=MsoNormal> <o:p></o:p></P><SPAN
style="COLOR: black; FONT-FAMILY: Arial; FONT-SIZE: 9pt; mso-fareast-font-family: SimSun; mso-fareast-language: EN-US; mso-ansi-language: EN-US; mso-bidi-language: AR-SA"><BR
clear=all style="PAGE-BREAK-BEFORE: always"></SPAN>
<P><B><SPAN style="COLOR: #0e3092; FONT-SIZE: 10pt">BSTRs
</SPAN></B></P>
<P>B-strings, more properly called Basic strings, are a special kind
of string format. Instead of comprising a classic array of
characters followed by a NUL character (code \0) that marks the
termination of the array, the structure of the data in memory is a
superset of OLECHAR. In short, a BSTR is a null-terminated array of
OLECHARs prefixed by its length. The string length is determined by
the character count, not by the index of the first null character.
</P>
<P>This presence of the length of the object before the actual array
data renders these strings suitable for manipulation in high-level
tools like Visual Basic (for which this string format was invented
in the first place) and Java on a COM-aware virtual machine like
Microsoft's JVM. Actually, there is no other way to exchange
string-like data with components written in those languages than to
employ BSTRs. While in C and C++ the developer has to understand and
use the data type in a rather uncomfortable manner, both Visual
Basic and Java encapsulate them into their traditional string types,
respectively String and java.lang.String. The final developer is
therefore shielded from the subtleties of the organization of the
raw bytes in memory. Moreover, the tools take care of allocating and
freeing the memory required to contain their content without the
programmer needing to know how this process works behind the scenes.
</P>
<P>This is the brilliant side of the medal of course. You as the
C/C++ hardcore engineer get the tough part of the work, since you
need to learn a completely new specific set of APIs that carry out
the basic operations with Basic strings. The family of functions is
amazingly named "system strings management API" and its members can
easily be distinguished by the "Sys" prefix in their names. </P>
<P>The following code snippet, borrowed from Oleauto.h (this stuff
used to be most useful when coupled with Automation, as Visual
Basic's COM support was a lot less powerful then), shows the
prototypes of each of the functions in the group: </P>
<TABLE border=0 cellPadding=0 cellSpacing=3
style="WIDTH: 100%; mso-cellspacing: 1.5pt; mso-padding-alt: 3.75pt 3.75pt 3.75pt 3.75pt"
width="100%">
<TBODY>
<TR>
<TD
style="BACKGROUND: #dfdfdf; PADDING-BOTTOM: 3.75pt; PADDING-LEFT: 3.75pt; PADDING-RIGHT: 3.75pt; PADDING-TOP: 3.75pt"><PRE>/*---------------------------------------------------------------------*/</PRE><PRE>/*<SPAN style="mso-spacerun: yes"> </SPAN>BSTR API<SPAN style="mso-spacerun: yes"> </SPAN>*/</PRE><PRE>/*---------------------------------------------------------------------*/</PRE><PRE> <o:p></o:p></PRE><PRE>WINOLEAUTAPI_(BSTR) SysAllocString(const OLECHAR *);</PRE><PRE>WINOLEAUTAPI_(INT)<SPAN style="mso-spacerun: yes"> </SPAN>SysReAllocString(BSTR *, const OLECHAR *);</PRE><PRE>WINOLEAUTAPI_(BSTR) SysAllocStringLen(const OLECHAR *, UINT);</PRE><PRE>WINOLEAUTAPI_(INT)<SPAN style="mso-spacerun: yes"> </SPAN>SysReAllocStringLen(BSTR *, const OLECHAR *, UINT);</PRE><PRE>WINOLEAUTAPI_(void) SysFreeString(BSTR);</PRE><PRE>WINOLEAUTAPI_(UINT) SysStringLen(BSTR);</PRE><PRE> <o:p></o:p></PRE><PRE>#ifdef _WIN32</PRE><PRE>WINOLEAUTAPI_(UINT) SysStringByteLen(BSTR bstr);</PRE><PRE>WINOLEAUTAPI_(BSTR) SysAllocStringByteLen(LPCSTR psz, UINT len);</PRE><PRE>#endif</PRE></TD></TR></TBODY></TABLE>
<P>Don't be unnerved by the probably unfamiliar
<I>WINOLEAUTAPI_()</I> word preceding all the functions; it is
simply a macro defined in the same header file that expands to a
long list of modifiers necessary to adjust the calling convention,
exportation details, and return type. You can blissfully ignore it
for our purposes. </P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -