您的位置:首页 > 其它

Understanding Strings In COM

2000-12-30 02:22 453 查看

UnderstandingStringsInCOM

ByDavideMarcato
SystemNotes
Toreplicatethestepsdescribedinthisarticle,you'llneedWindows95+orWindowsNT4.0+andVisualC++5.0orhigher.
ANSIandUnicode,charandwchar_twerenotenough:COMintroducedseveralnewstringdatatypes,andthedifferencesandtheprocessofconversionarenotalwaysobvioustotheuninitiated.ThisarticleclarifiesthesituationonceandforallforthebenefitofrawCOM,ATLandMFCprogrammers.
Strings,i.e.vectorsofalphanumericcharacters,areandhavealwaysbeenafundamentaldatatypeineveryprogramminglanguageandplatform.Whereasthecomputeritselfpreferstodealwithnumbers,humanbeingsprefermessagesoftexttosequencesofbinary,hexadecimalorevendecimaldigits.Thisimpliesthatwheneverapieceofsoftwareneedstointeractwiththeuser(orsignalsomenotableevents)somekindofstringtreatmentislikelytocomeintoplay.
Untilafewyearsagostringswerejuststrings,thatis,arraysofsingle-bytedatatypes(charinC/C++)containingtheASCIInumberofthecharacterateachelement.Thebiggestproblemwasdistinguishingzero-terminatedstrings(alsoknownasASCIIZ)fromnon-zero-terminatedarrays.ThencameUnicode,anewcharactersetwhichextendedthesizeofeachcharacterfrom8to16bits,thusallowingfor65536theoreticaldifferentcharacters,enoughtocontainalsoFarEasternsymbolssuchastheKanjistandardset.InC/C++abrandnewstandarddatatypewasdefinedtostoreUnicodestrings,wchar_t,andconsequentlytheAPIsofUnicode-awareWin32operatingsystemsthattookstringsasparametershadtobeduplicatedtoacceptbothANSIandUnicodeversions.
JustastheWindowsprogrammercommunitybegantogetacquaintedwiththisduplicationandgotintothehabitofnotassuminganythingaboutthelengthofacharacterapriori,COMjumpedtothecentralstagewithitsburdenofnewtypesandaliases.IfyouarewonderingwhatisthefunctionaldifferencebetweenanarrayofOLECHARsandapointertoaBSTR,whenandhowitisnecessarytoconvertastringtoanothertype,andwhatdegreeofassistanceATLandMFCoffertothedeveloper,thisarticleisforyou.
OLECHARs
ThemainstringdatatypeinCOMisnamedOLECHAR,whichisthekindofvariableexpectedbyalmostallCOMlibraryfunctionsandwell-educatedinterfaces'methods.AnOLECHARrepresentsasingleOLE-compatiblecharacter,thereforeyoucanspeakofastringonlywhenyouhaveanarrayofOLECHARs.ItisobvioustoeveryonewhohasutilizedC++forsometimethatthereisnotanOLECHARbuilt-indatatypeinthelanguage,asunderlined(amongotherthings)bytheuppercaseofthename.TheCandC++standardspecificationsdictatetheexistenceofonlytwocharactertypes:charandwchar_t.Hence,OLECHARmustbeanaliastooneofthem,andinfactitis.ItsrelationisestablishedbythestandardWin32headerfilewtypes.h,whichwewillmeetagainlaterinthisarticle.Thefollowingcodesnippet,adaptedfromtheheaderfileforclarity,representstheofficialdefinitionofOLECHARinC/C++:
#ifdefined(_WIN32)&&!defined(OLE2ANSI)

typedefWCHAROLECHAR;

#else

typedefcharOLECHAR;

#endif

ThesamefiledefinesalsotheLPOLESTRandLPCOLESTRtypes:
#ifdefined(_WIN32)&&!defined(OLE2ANSI)

typedefOLECHAR__RPC_FAR*LPOLESTR;

typedefconstOLECHAR__RPC_FAR*LPCOLESTR;

#else

typedefLPSTRLPOLESTR;

typedefLPCSTRLPCOLESTR;

#endif

asaliasesofOLECHAR*andconstOLECHAR*inWin32,butaliasesofLPSTRandLPCSTRinWindows3.1x.The__RPC_FARsymbolcanbeignoredasitexpandstonothing,soforallpracticalpurposesBSTRandOLECHAR*canbedeployedinterchangeably.
Asyoucansee,theBSTRtypedoesnotmaptothesameactualbuilt-intypeoneveryplatform.Ifthecodeiscompiledon32-bitWindows,whichcanbedetectedfromthe_WIN32preprocessorsymboldefinition,allCOMcharactersareUnicodestring(WCHARisitselfatypedef'eddatatypethattranslatestothebuilt-inwchar_ttype).Ifnot,thenthebuildcommandisprobablytargetingWindows3.1x,whichdoesnotsupportUnicodestringsatall,soallthestringsareregularoldarraysofchar.NotethatonSunSolaris,themainUNIXflavortobenefitfromaportingofthe(D)COMimplementationtodate,OLECHARsare16-bitUnicodecharactersexactlyasonWin32.
TheoriginalMicrosoftengineerswhodesignedCOMmadeaprettycourageousdecision:TheydefactoimposedUnicodetoeveryoneinthe32-bitworldatatimewhentheoriginalversionofWindowsNTwasbarelytakingshapeandthedoubledamountofRAMrequiredtoholdthesamestringscouldeasilybecomeproblematicduetothehighcostofmemory.Butthedecisionprovedadvantageous,asitsavedCOMdevelopersfromhavingtoimplementtwovariantsofeachinterface(andrelativecoclassesimplementingit)justtodealwitheverypossibletypeofclient.
NowwehaveseenhowtodefineaCOM-compliantcharacterandbyextensionaCOM-compliantstring,butwehavenotrevealedyethowonecaninitializesuchastringwithastringliteral.Thefollowingstatement:
constOLECHAR*pComStr;

pComStr="IloveVCDJandCOM";

doesworkinWindows3.1xbecauseonlyANSIstringsexistthere,butwillfailtocompileonWin32andSolarisbecausewearetryingtocopyanANSIstringtoaUnicodearrayofcharacters.Thefollowingform:
constOLECHAR*pComStr;

pComStr=L"IloveVCDJandCOM";

willgivetheexactoppositeresults:workingonWin32,incorrectonWindows3.1.Whatwereallyneedisawaytodefinethetypeofastringirrespectiveoftheplatform.Nothingcouldfitthebillbetterthanamacro,asinthecodebelow:
constOLECHAR*pComStr;

pComStr=OLESTR("IloveVCDJandCOM");

TheOLESTR()macroistranslateddifferentlydependingonthetargetofthebuildprocess,soweobtainthecorrectdefinitioninallcases.Wtypes.hreportsitasfollows,withsomesecondaryadjustmentsmadetoclarifytheoriginalcode:
#ifdefined(_WIN32)&&!defined(OLE2ANSI)

#defineOLESTR(str)L##str

#else

#defineOLESTR(str)str

#endif

Note:InallotherWin32APIimplementationsthereisadiscrepancybetweenWindows95/Windows98andWindowsNT'sstringtreatment,sincetheformeremploysone-byteANSIcharactersandthelatterinternallyworksonlywithtwo-byteUnicodecharacters.However,whenitcomestoCOM,bothoperatingsystemsagreeontheuseofUnicodestrings.
AtthispointyoumaybecuriousastowhythedatatypewascalledOLECHARratherthanthemoreobviousCOMCHAR.Theanswertothisquestionhasitsrootspartlyinhistoryandpartlyinmarketing:untilafewyearsagoOLE2,themainfamilyoftechnologiesrelyingontheCOMfoundation,wasdeemedmoreimportantthanCOMitself,hencetheacronymOLEspreadeverywhere.ThelaterchangeofmarketingorientationcouldnotbereflectedinthesymbolnamestoavoidbreakingalotofexistingandcorrectlyfunctioningCOM/OLEcode.(SeemyQ&AcolumninVCDJprintandonlineforextensiveinfoonthissometimesuncleartransitionoftermsandintents.)
OLECHARsarethestandardwaytocreatestringsinCOMcodeandbyfarthemostcomfortableaslongasCandC++areusedinboththeclientsideandtheserverside.Otherlanguagesandtoolsbringtheirburdenofspecialconstraintsthatopenthewaytoanotherkindofstring,whichconstitutethetopicofthenextparagraph.
continued...

Copyright©1999-VisualC++DevelopersJournal
BSTRs

B-strings,moreproperlycalledBasicstrings,areaspecialkindofstringformat.InsteadofcomprisingaclassicarrayofcharactersfollowedbyaNULcharacter(code/0)thatmarkstheterminationofthearray,thestructureofthedatainmemoryisasupersetofOLECHAR.Inshort,aBSTRisanull-terminatedarrayofOLECHARsprefixedbyitslength.Thestringlengthisdeterminedbythecharactercount,notbytheindexofthefirstnullcharacter.

Thispresenceofthelengthoftheobjectbeforetheactualarraydatarendersthesestringssuitableformanipulationinhigh-leveltoolslikeVisualBasic(forwhichthisstringformatwasinventedinthefirstplace)andJavaonaCOM-awarevirtualmachinelikeMicrosoft'sJVM.Actually,thereisnootherwaytoexchangestring-likedatawithcomponentswritteninthoselanguagesthantoemployBSTRs.WhileinCandC++thedeveloperhastounderstandandusethedatatypeinaratheruncomfortablemanner,bothVisualBasicandJavaencapsulatethemintotheirtraditionalstringtypes,respectivelyStringandjava.lang.String.Thefinaldeveloperisthereforeshieldedfromthesubtletiesoftheorganizationoftherawbytesinmemory.Moreover,thetoolstakecareofallocatingandfreeingthememoryrequiredtocontaintheircontentwithouttheprogrammerneedingtoknowhowthisprocessworksbehindthescenes.

Thisisthebrilliantsideofthemedalofcourse.YouastheC/C++hardcoreengineergetthetoughpartofthework,sinceyouneedtolearnacompletelynewspecificsetofAPIsthatcarryoutthebasicoperationswithBasicstrings.Thefamilyoffunctionsisamazinglynamed"systemstringsmanagementAPI"anditsmemberscaneasilybedistinguishedbythe"Sys"prefixintheirnames.

Thefollowingcodesnippet,borrowedfromOleauto.h(thisstuffusedtobemostusefulwhencoupledwithAutomation,asVisualBasic'sCOMsupportwasalotlesspowerfulthen),showstheprototypesofeachofthefunctionsinthegroup:

/*---------------------------------------------------------------------*/

/*BSTRAPI*/

/*---------------------------------------------------------------------*/


WINOLEAUTAPI_(BSTR)SysAllocString(constOLECHAR*);

WINOLEAUTAPI_(INT)SysReAllocString(BSTR*,constOLECHAR*);

WINOLEAUTAPI_(BSTR)SysAllocStringLen(constOLECHAR*,UINT);

WINOLEAUTAPI_(INT)SysReAllocStringLen(BSTR*,constOLECHAR*,UINT);

WINOLEAUTAPI_(void)SysFreeString(BSTR);

WINOLEAUTAPI_(UINT)SysStringLen(BSTR);


#ifdef_WIN32

WINOLEAUTAPI_(UINT)SysStringByteLen(BSTRbstr);

WINOLEAUTAPI_(BSTR)SysAllocStringByteLen(LPCSTRpsz,UINTlen);

#endif

Don'tbeunnervedbytheprobablyunfamiliarWINOLEAUTAPI_()wordprecedingallthefunctions;itissimplyamacrodefinedinthesameheaderfilethatexpandstoalonglistofmodifiersnecessarytoadjustthecallingconvention,exportationdetails,andreturntype.Youcanblissfullyignoreitforourpurposes.

Thefollowingtablebrieflydescribesthetaskofeachroutine:

Functionname
Description
SysAllocString()
AllocatesanewBSTRandinitializesitwithanOLECHAR*
SysReAllocString()
ReallocatesanexistingBSTRandinitializesitwithanOLECHAR*
SysAllocStringLen()
AllocatesanewBSTR,copiesaspecifiednumberofcharactersfromthepassedOLECHAR*intoit,andthenappendsanullcharacter
SysReAllocStringLen()
ReallocatesanexistingBSTR,copiesaspecifiednumberofcharactersfromthepassedOLECHAR*intoit,andthenappendsanullcharacter
SysFreeString()
DeallocatesaBSTR
SysStringLen()
ReturnsthenumberofcharactersinaBSTR
SysStringByteLen()
ReturnsthelengthinbytesofaBSTR(Win32only)
SysAllocStringByteLen()
AllocatesaBSTRthatcontainstheANSIstringpassedasaparameter.DoesnotperformanyANSI-to-Unicodetranslation(Win32only)
Thesuccinctdescriptionprovidedabove,inconjunctionwiththeofficialdocumentation,shouldbeeverythingyouwilleverneedtoknowtodealwithBSTRs.NotethattheexpectedusagepatternisthepreventiveallocationofanarrayofOLECHARs,whichislatercopiedintothesystemstring.

Basicstringsmustbeallocatedandfreedmanually.Butwhohastheresponsibilityofdoingsowhenfunctioncallsareinvolved?ThisisageneralCOMquestionandsotheanswerdoesnotapplysolelytostrings.Iftheparameterisinput-only(IDLattribute[in])thecallerisresponsibleforboththecreationandthedestructionofthevariable.Iftheparameterisoutput-only(IDLattribute[out])thenthecalleeisresponsiblefortheallocationofthestring,butthecallerisexpectedtofreeitafteruse.Iftheparameterisbothinputandoutput(IDLattribute[in,out])thenthecallerallocatesthestringandafterthemethodinvocationfreesthememory.Thecalleethoughisallowedtoreallocatethestringifnecessarytodosobeforereturningittothecaller.

ObviouslythesedetailsinterestC/C++developersonly,asVisualBasicwillcontinuetotreatstringsasusualwithoutanyspecialconsideration.

BSTRwrappers

BothATLandMFCofferparticularsupportforsimplifiedBSTRmanagement.ATLdoesitbymeansofaspecializedwrapperclass,CComBSTR,whosedeclarationinatlbase.hlookslikethefollowing(strippeddownasusualforclarityandspaceconstraints):

classCComBSTR

{

public:

BSTRm_str;

CComBSTR();

CComBSTR(intnSize,LPCOLESTRsz=NULL);

CComBSTR(LPCOLESTRpSrc);

CComBSTR(constCComBSTR&src);

CComBSTR&operator=(constCComBSTR&src);

CComBSTR&operator=(LPCOLESTRpSrc);

~CComBSTR();

unsignedintLength()const;

operatorBSTR()const;

BSTR*operator&();

BSTRCopy()const;

voidAttach(BSTRsrc);

BSTRDetach();

voidEmpty();

#if_MSC_VER>1020

booloperator!();

#else

BOOLoperator!();

#endif

voidAppend(constCComBSTR&bstrSrc);

voidAppend(LPCOLESTRlpsz);

voidAppendBSTR(BSTRp);

voidAppend(LPCOLESTRlpsz,intnLen);

CComBSTR&operator+=(constCComBSTR&bstrSrc);

#ifndefOLE2ANSI

CComBSTR(LPCSTRpSrc);

CComBSTR(intnSize,LPCSTRsz=NULL);

CComBSTR&operator=(LPCSTRpSrc);

voidAppend(LPCSTR);

#endif

HRESULTWriteToStream(IStream*pStream);

HRESULTReadFromStream(IStream*pStream);

};

Theutilizationoftheclassisverystraightforwardevenforthenon-ATLexperts.Basicallythefeaturesofferedare:

encapsulationoftheallocationanddeallocationprocedureswithintheconstructoranddestructor;

duplicationofthecontents(throughCComBSTR::Copy());

possibilitytoappendalmostanykindofstringtothewrappedBSTRexploitingtheoverloadingfeatureofC++;

supportforreadablestringcomparisonsthroughthecustomized!operator;

basicI/Ooperationstostorethecontentsofthestringto,andretrieveitfrom,astructuredstoragestream.

Ontheotherhand,MFCdoesnotprovideanydirectwrapperclassforsystemstrings.AllthesupportisanintegralpartoftheextremelyversatileCstringclass.Asshowninthefollowingcodesnippetborrowedfromtheclass'sprototypeinafx.h,thereareonlyacoupleofmethodsspecificallygeneratingCOMstrings:

//OLEBSTRsupport(useforOLEautomation)

BSTRAllocSysString()const;

BSTRSetSysString(BSTR*pbstr)const;

InternallyCString::AllocSysString()allocatesanewBSTRusingtheAPIsweexaminedinanearlierparagraphandcopiesitscontentstothenewlycreatedsystemstring,whichiseventuallyreturnedtothecaller.ThereisnosuchfunctionasCString::FreeSysString(),sotodeallocatethememoryoccupiedbythereturnedBSTR,theglobalAPI::SysFreeString()willhavetobecalled.CString::SetSysString()insteadreallocatestheBSTRpointedtobytheparameterandcopiesitscontentsintoit.BothmethodsthrowCmemoryExceptionexceptionobjectsincaseofmemoryallocationproblems.

Moreover,ifyouareusingVisualC++5.0orhigher,youcanexploittheDirectToCOMproprietaryextensionwhichincludes,amongmanyotherthings,a_bstr_tclass.Thedocumentationreportsthatitisdefinedinsidecomdef.h,whileinrealityitsdeclarationresidesincomutil.h.ThedegreeofencapsulationandfunctionalityissimilartoATL'sCComBSTR,butrememberthatusingtheCOMcompilersupportbindsyoutoVisualC++evenmorethanATLwoulddo.Probablythemostrelevantdifferencebetweenthetwoimplementationsisthat_bstr_traisesC++exceptionsandthusrequiresyourcodetobepreparedtocatchthem,whereasCComBSTRdoesnot.Thisdetailwilllikelyinfluenceyourchoicemorethanalltheotherpossibleconsiderations.Thefollowingcodelistingsummarizesthepublicinterfaceof_bstr_t;thecommentsshouldmakeiteasytounderstandwhatthediversemethodgroupsareupto:

class_bstr_t{

public:

//Constructors

//

_bstr_t()throw();

_bstr_t(const_bstr_t&s)throw();

_bstr_t(constchar*s)throw(_com_error);

_bstr_t(constwchar_t*s)throw(_com_error);

_bstr_t(const_variant_t&var)throw(_com_error);

_bstr_t(BSTRbstr,boolfCopy)throw(_com_error);


//Destructor

//

~_bstr_t()throw();


//Assignmentoperators

//

_bstr_t&operator=(const_bstr_t&s)throw();

_bstr_t&operator=(constchar*s)throw(_com_error);

_bstr_t&operator=(constwchar_t*s)throw(_com_error);

_bstr_t&operator=(const_variant_t&var)throw(_com_error);


//Operators

//

_bstr_t&operator+=(const_bstr_t&s)throw(_com_error);

_bstr_toperator+(const_bstr_t&s)constthrow(_com_error);


//Friendoperators

//

friend_bstr_toperator+(constchar*s1,const_bstr_t&s2);

friend_bstr_toperator+(constwchar_t*s1,const_bstr_t&s2);


//Extractors

//

operatorconstwchar_t*()constthrow();

operatorwchar_t*()constthrow();

operatorconstchar*()constthrow(_com_error);

operatorchar*()constthrow(_com_error);


//Comparisonoperators

//

booloperator!()constthrow();

booloperator==(const_bstr_t&str)constthrow();

booloperator!=(const_bstr_t&str)constthrow();

booloperator<(const_bstr_t&str)constthrow();

booloperator>(const_bstr_t&str)constthrow();

booloperator<=(const_bstr_t&str)constthrow();

booloperator>=(const_bstr_t&str)constthrow();


//Low-levelhelperfunctions

//

BSTRcopy()constthrow(_com_error);

unsignedintlength()constthrow();


private:

//[...privatestuffomitted...]

}

continued...

Copyright©1999-VisualC++DevelopersJournal
Frameworksandconversions

YourideasofOLECHARandBSTRandyourunderstandingofthemannerCOMhandlesstringsshouldbemuchclearernow,butwestillhavetocopewithtypeconversionstoandfromthesesomewhatspecialdatatypesandthemoretraditionalTCHAR,WCHARandchar.

ATLandMFCbothusethesamegroupofmacrostodealwithstringconversions.Thesemacros'namesfollowapreciseconvention:thecharactersbeforethe"2"indicatetheoriginaltypeofthevariabletoconvert,andthecharactersafterthe"2"indicatethedestinationtypeaftertheconversion.Thefollowingtableliststhevalidsymbolsinaconversionmacroname:

Shortname
Datatype
A
LPSTR,char*
OLE
LPOLESTR
T
LPTSTR,TCHAR*
W
LPWSTR,wchar_t*
BSTR
BSTR
C
const-associatedtoanothertype
Themacrosoperateintelligently:ifforsomereasonthesourceanddestinationtypescoincide,thecodedoesnotwastetimeinauselessprocess.Internallymostofthemacroscallthe_alloca()run-timelibraryfunctionandallocatethestorageforthenewdataonthestack,asthissimplifiesthedeallocationpolicybydelegatingittotherulesofthevariablesscope.Forthisreason,aUSES_CONVERSIONmacromustbeputjustbeforetheconversionoperationineachfunctionorclassmethodthatcontainsthemacros.Thefollowingsamplecode,takenfromthedownloadablesamplepackavailableontheWeb,willclarifytheprocess:

//ConversionsthroughMFC/ATL'smacros

voidSample2()

{

USES_CONVERSION;


//ANSI

LPSTRansiStr="Thisisasamplemessage";

printf("BEFOREthestringcontains:%s/n",ansiStr);


//ANSI->constTCHAR

constTCHAR*pTChar=A2CT(ansiStr);

_tprintf(_T("MIDWAYthestringcontains:%s/n"),pTChar);


//constTCHAR->Unicode

LPWSTRwStr=T2W(pTChar);

wprintf(L"AFTERthestringcontains:%s/n",wStr);

}

AsIstatedearlier,theconversionmacrosarepartofMFCandATL,butsurprisinglytheheaderfilesarenotdirectlysharedbythetwoframeworks.ATLprogrammersshouldincludeAtlconv.h,whileMFCdevelopersaresupposedtoincludeAfxconv.hintheirprojects.AfterdiggingintothesourcesIfoundthatinthelatestversionsofMFC,Afxconv.hdoeslittlemorethanincludeAtlconv.hitself,soinpracticethestringconversioncodeexposedbythetwoframeworksisthesame.

TheCOMcompilersupportoffersgoodBSTRconversioncode,too.Theactualconversionfunctionsarethecastoperatorsthatconverta_bstr_ttoeitheranANSIoraUnicodestring,eitherconstantornot,plustheomnipresentclassconstructors.Thefollowingcodesnippet,takenfromthedownloadablesamplepackavailableontheWeb,showssomecommonusagepatternsofBSTRconversions:

//BSTRconversions

voidSample3()

{

USES_CONVERSION;


LPWSTRwStr=L"Thisisasamplemessage";

wprintf(L"BEFOREthestringcontains:%s/n",wStr);


BSTRbstr1=W2BSTR(wStr);


CStringmfcStr=bstr1;

printf("MIDWAYthestringcontains:%s/n",(LPCSTR)mfcStr);


BSTRbstr2=mfcStr.AllocSysString();

_bstr_tbstr3=bstr2;

VERIFY(bstr3==(_bstr_t)bstr1);


WCHAR*wStr2=bstr3;

wprintf(L"AFTERthestringcontains:%s/n",wStr2);


::SysFreeString(bstr1);

::SysFreeString(bstr2);

}

Thisismusictotheearsofthosewhoworkwithmoreorlessadvancedframeworks,butwhataboutthosewhoprefer(orarecompelled)tosticktolow-levelC++COMdevelopment?Theycanstillusethestandardlibraryconversionfunction,whichtheframeworkmacrosthemselvesrelyonultimately,suchasmbstowcs()andwcstombs().UnfortunatelysuchfunctionsarenotawareofBSTRsandOLECHARs,soheavyuseofconditionalcompilationwouldberequiredtodealwiththevariouscombinationspossible,andthisisevilfromareadabilityperspective.PowerdeveloperswhoprogramCOMattherawC++levelwillprobablyfindoutnaturallyatacertainpointintheirlearningcurveandexperiencehowtowriteasetofconversionmacrosbythemselves.Ifyouarelazyandprefertouseaprecookedsetofmacros,youcanfreelyuseDonBox'sYACL(theacronymstandsfor"YetAnotherCOMLibrary")whichisextremelyefficientanddoesmuchmorethanjuststringconversioninpureC++COM.TheURLforthedownloadishttp://www.develop.com/dbox/yacl.htm.
Conclusion

Aftersomestudyanddirectexperimentation,thevariousstringtypesinCOMprovetobemuchlesscrypticandproblematicthanatfirsttheyseemed.Fundamentally,itallboilsdowntorecognizingandmemorizingahandfulofnewdatatypeswhichmaybehavedifferentlyondifferentplatforms,andgettingusedtotheframeworkofhandyconversionfunctionsprovidedbyATL,MFC,ortheDirectToCOMVisualC++extension.Regardlessofwhichofthementionedtasksyouaregoingtotackle,Ihopethisarticlewillserveasavaluableaidinsavingprecioustimeworkingwithstrings.

articleindex

Copyright©1999-VisualC++DevelopersJournal
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐