Connecting C++ and XAML
2015-10-07 19:07
555 查看
TheBuildProcess
Fromauser-facingstandpoint,Pagesandothercustomcontrolsarereallyatrioofuser-editablefiles. Forexample,thedefinitionoftheclassMainPageiscomprisedofthreefiles:MainPage.xaml,MainPage.xaml.h,andMainPage.xaml.cpp. Bothmainpage.xamlandmainpage.xaml.hcontributetotheactualdefinitionoftheMainPageclass,whileMainPage.xaml.cppprovidesthemethodimplementationsforthosemethodsdefinedinMainPage.xaml.h. However,how
thisactuallyworksinpracticeisfarmorecomplex.
Thisdrawingisverycomplex,sopleasebearwithmewhileIbreakitdownintoitsconstituentpieces.
Everyboxinthediagramrepresentsafile. Thelight-bluefilesontheleftsideofthediagramarethefileswhichtheuseredits. ThesearetheonlyfilesthattypicallyshowupintheSolution
Explorer. I’llspeakspecificallyaboutMainPage.xamlanditsassociatedfiles,butthissameprocessoccursfo
4000
rallxaml/h/cpptriosintheproject.
ThefirststepinthebuildisXAMLcompilation,whichwillactuallyoccurinseveralsteps. First,theuser-editedMainPage.xamlfileisprocessedtogenerateMainPage.g.h. Thisfileisspecial
inthatitisprocessedatdesign-time(thatis,youdonotneedtoinvokeabuildinordertohavethisfilebeupdated). ThereasonforthisisthateditsyoumaketoMainPage.xamlcanchangethecontentsoftheMainPageclass,andyouwantthosechanges
tobereflectedinyourIntellisensewithoutrequiringarebuild. Exceptforthisstep,alloftheotherstepsonlyoccurwhenauserinvokesaBuild.
PartialClasses
Youmaynotethatthebuildprocessintroducesaproblem:theclassMainPageactuallyhastwodefinitions,onethatcomesfromMainPage.g.h:partialrefclassMainPage:public::Windows::UI::Xaml::Controls::Page, public::Windows::UI::Xaml::Markup::IComponentConnector { public: voidInitializeComponent(); virtualvoidConnect(intconnectionId,::Platform::Object^target); private: bool_contentLoaded; };
AndonethatcomesfromMainPage.xaml.h:
publicrefclassMainPagesealed { public: MainPage(); protected: virtualvoidOnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^e)override; };
Thisissueisreconciledviaanewlanguageextension:PartialClasses.
Thecompilerparsingofpartialclassesisactuallyfairlystraightforward. First,allpartialdefinitionsforaclassmustbewithinonetranslationunit. Second,allclassdefinitionsmustbemarked
withthekeyword partial exceptfortheverylastdefinition(sometimesreferredtoasthe‘final’definition). Duringparsing,thepartialdefinitionsaredeferredbythecompileruntil
thefinaldefinitionisseen,atwhichpointallofthepartialdefinitions(alongwiththefinaldefinition)arecombinedtogetherandparsedasonedefinition. ThisfeatureiswhatenablesboththeXAML-compiler-generatedfileMainPage.g.handtheuser-editable
fileMainPage.xaml.htocontributetothedefinitionoftheMainPageclass.
Compilation
Forcompilation,MainPage.g.hisincludedinMainPage.xaml.h,whichisfurtherincludedinMainPage.xaml.cpp. ThesefilesarecompiledbytheC++compilertoproduceMainPage.obj. (Thiscompilationisrepresentedbytheredlinesintheabovediagram.) MainPage.obj,alongwiththeotherobjfilesthatareavailableatthisstagearepassedthroughthelinkerwiththeswitch/WINMD:ONLYtogeneratetheWindowsMetadata(WinMD)filefortheproject.This
processisdenotedinthediagrambytheorangeline. Atthisstagewearenotlinkingthefinalexecutable,onlyproducingtheWinMDfile,becauseMainPage.objstillcontainssomeunresolvedexternalsfortheMainPageclass,namelyanyfunctionswhichare
definedinMainPage.g.h(typicallytheInitializeComponentandConnectfunctions). ThesedefinitionsweregeneratedbytheXAMLcompilerandplacedintoMainPage.g.hpp,whichwillbecompiledatalaterstage.
MainPage.g.hpp,alongwiththe*.g.hppfilesfortheotherXAMLfilesintheproject,willbeincludedinafilecalledXamlTypeInfo.g.cpp. Thisisforbuildperformanceoptimization:thesevarious
.hppfilesdonotneedtobecompiledseparatelybutcanbebuiltasonetranslationunitalongwithXamlTypeInfo.g.cpp,reducingthenumberofcompilerinvocationsrequiredtobuildtheproject.
DataBindingandXamlTypeInfo
DatabindingisakeyfeatureofXAMLarchitecture,andenablesadvanceddesignpatternssuchasMVVM. C++fullysupportsdatabinding;however,inorderfortheXAMLarchitecturetoperformdatabinding,itneedstobeabletotakethestringrepresentationofafield(suchas“FullName”)andturnthatintoapropertygettercallagainstanobject. Inthemanagedworld,thiscanbeaccomplishedwithreflection,butnativeC++doesnothaveabuilt-in
reflectionmodel.
Instead,theXAMLcompiler(whichisitselfa.NETapplication)loadstheWinMDfilefortheproject,reflectsuponit,andgeneratesC++sourcethatendsupintheXamlTypeInfo.g.cppfile. It
willgeneratethenecessarydatabindingsourceforanypublicclassmarkedwiththeBindableattribute.
Itmaybeinstructivetolookatthedefinitionofadata-bindableclassandseewhatsourceisgeneratedthatenablesthedatabindingtosucceed. Hereisasimplebindableclassdefinition:
[Windows::UI::Xaml::Data::Bindable] publicrefclassSampleBindableClasssealed{ public: propertyPlatform::String^FullName; };
Whenthisiscompiled,astheclassdefinitionispublic,itwillendupintheWinMDfileasseenhere:
ThisWinMDisprocessedbytheXAMLcompilerandaddssourcetotwoimportantfunctionswithinXamlTypeInfo.g.cpp: CreateXamlType and CreateXamlMember .
Thesourceaddedto CreateXamlType generatesbasictypeinformationfortheSampleBindableClass type,
providesanActivator(afunctionthatcancreateaninstanceoftheclass)andenumeratesthemembersoftheclass:
if(typeName==L"BlogDemoApp.SampleBindableClass")
{
XamlUserType^userType=refnewXamlUserType(this,typeName,GetXamlTypeByName(L"Object"));
userType->KindOfType=::Windows::UI::Xaml::Interop::TypeKind::Custom;
userType->Activator=
[]()->Platform::Object^
{
returnrefnew::BlogDemoApp::SampleBindableClass();
};
userType->AddMemberName(L"FullName");
userType->SetIsBindable();
returnuserType;
}
Notehowalambdaisusedtoadaptthecallto refnew (whichwillreturnaSampleBindableClass^ )
intothe Activator function(whichalwaysreturnsan Object^ ).
FromStringtoFunctionCall
AsImentionedpreviously,thefundamentalissuewithdatabindingistransformingthetextnameofaproperty(inourexample,“FullName”)intothegetterandsetterfunctioncallsforthisproperty. Thistranslationmagicisimplementedbythe XamlMember class.
XamlMember storestwofunctionpointers: Getter and Setter . Thesefunction
pointersaredefinedagainstthebasetype Object^ (whichallWinRTandfundamentaltypescanconvertto/from). A XamlUserType stores
a map<String^,XamlUserType^> ;whendatabindingrequiresagetterorsettertobecalled,theappropriate XamlUserType canbe
foundinthemapanditsassociated Getter or Setter functionpointercanbeinvoked.
Thesourceaddedto CreateXamlMember initializesthese Getter and Setter function
pointersforeachproperty. ThesefunctionpointersalwayshaveaparameteroftypeObject^ (theinstanceoftheclasstogetfromorsetto)andeitherareturnparameteroftypeObject^ (in
thecaseofagetter)orhaveasecondparameteroftype Object^ (forsetters).
if(longMemberName==L"BlogDemoApp.SampleBindableClass.FullName")
{
XamlMember^xamlMember=refnewXamlMember(this,L"FullName",L"String");
xamlMember->Getter=
[](Object^instance)->Object^
{
autothat=(::BlogDemoApp::SampleBindableClass^)instance;
returnthat->FullName;
};
xamlMember->Setter=
[](Object^instance,Object^value)->void
{
autothat=(::BlogDemoApp::SampleBindableClass^)instance;
that->FullName=(::Platform::String^)value;
};
returnxamlMember;
}
Thetwolambdasdefinedusethelambda‘decaytopointer’functionalitytobindto Getterand Setter methods.
Thesefunctionpointerscanthenbecalledbythedatabindinginfrastructure,passinginanobjectinstance,inordertosetorgetapropertybasedononlyitsname. Withinthelambdas,thegeneratedcodeaddsthepropertypecastsinordertomarshalto/from
theactualtypes.
FinalLinkingandFinalThoughts
Aftercompilingthexamltypeinfo.g.cppfileintoxamltypeinfo.g.obj,wecanthenlinkthisobjectfilealongwiththeotherobjectfilestogeneratethefinalexecutablefortheprogram. Thisexecutable,alongwiththewinmdfilepreviouslygenerated,andyourxamlfiles,arepackagedupintotheapppackagethatmakesupyourWindowsStoreApplication.
Anote:theBindableattributedescribedinthispostisonewaytoenabledatabindinginWinRT,butitisnottheonlyway. Databindingcanalsobeenabledonaclassbyimplementingeither
theICustomPropertyProviderinterfaceorIMap<String^,Object^>. TheseotherimplementationswouldbeusefuliftheBindableattributecannotbeused,particularlyifyouwantanon-publicclasstobedata-bindable.
Foradditionalinfo,Irecommendlookingat this
walkthrough ,whichwillguideyouthroughbuildingafully-featuredWindowsStoreApplicationinC++/XAMLfromthegroundup. TheMicrosoftPatternsandPracticesteamhasalsodeveloped
alargeapplicationwhichdemonstratessomebestpracticeswhendevelopingWindowsStoreApplicationsinC++:projectHilo. Thesourcesanddocumentationforthisprojectcanbefoundat
(NotethatthisprojectmaynotyetbeupdatedfortheRTMreleaseofVisualStudio.)
Ihopethisposthasgivenyousomeinsightintohowuser-editedfilesandgeneratedfilesarecompiledtogethertoproduceafunctional(andvalid)C++program,andgivenyousomeinsightinto
howtheXAMLdatabindinginfrastructureactuallyworksbehindthescenes.
相关文章推荐
- 项目33.1利用循环求和
- 又开了一个C语言最强最全班
- C++实现KMP算法(优化版)
- 【C语言】求1-1/2+1/3-1/4+1/5....+1/99-1/100
- /*捕食者与被捕食者求大神解题C++.*/
- C++ AES之CBC加密模式
- C++实现KMP算法(修正版,C++风格)
- C++11中的std::bind
- C语言变量
- Windows下使用C++获取目录及子目录下所有文件
- C++字符串(String)
- C/C++之数组与指针关系-全解全息
- C++实现KMP算法(单值返回版)
- 【C语言】1到100中9的个数
- C语言:求出0~999之间的所有“水仙花数”并输出
- iOS开发-【C语言】三目运算符
- 在屏幕上输出图案:*与空格拼出的菱形
- C语言:编写程序数一下 1到 100 的所有整数中出现多少次数字 9
- 面试复习(C++)之堆排序
- c++ primer 第五章习题