Бүгін біз өзіңіздің жобаңызға байланыстыруларды қалай жасауға болатынын қарастырамыз.
Qt компаниясы Python-ға арналған Qt құрамына сіздің негізгі байланыстыру құралы Shiboken де кіретінін қуана хабарлайды.
Төмендегі материалды оқып шығыңыз және сіз қарапайым C++ кітапханасы үшін Python байланыстарын жасау туралы түсінік аласыз.
Бұл сізді өзіңіздің жеке кітапханаларыңызбен бірдей істеуге шақырады деп үміттенеміз.
Кез келген Qt жобасы сияқты, біз Shiboken туралы мақалаларды беруге қуаныштымыз, осылайша оның барлығына түсінікті жақсартамыз.
Кітапхана үлгісі
Бұл жазбаның негізгі мақсаты - Universe деп аталатын аздап мағынасыз пайдаланушы кітапханасын пайдалану. Ол екі сыныпты ұсынады: балмұздақ (балмұздақ) және жүк көлігі (жүк көлігі).
Балмұздақ дәмімен сипатталады, ал Жүк машинасы маңайдағы балаларға балмұздақ жеткізу құралы ретінде қызмет етеді. Өте қарапайым.
Біз бұл сыныптарды Python ішінде пайдаланғымыз келеді. Қолданылатын жағдай қосымша балмұздақ дәмін қосу немесе балмұздақ жеткізудің сәтті болғанын тексеру болып табылады. Қарапайым тілмен айтқанда, біз балмұздақ пен жүк көлігіне арналған Python байланыстыруларын ұсынғымыз келеді, осылайша біз оларды Python сценарийінде пайдалана аламыз.
Біз қысқаша болу үшін кейбір бөліктерді өткізіп жібереміз, бірақ сіз толық бастапқы кодты алу үшін репозиторийді тексере аласыз. Репозиторийге сілтеме pyside-setup/examples/samplebinding .
C++ кітапханасы
Алдымен, Icecream тақырып файлын қарастырайық
class Icecream { public: Icecream(const std::string &flavor); virtual Icecream *clone(); virtual ~Icecream(); virtual const std::string getFlavor(); private: std::string m_flavor; };
және жүк көлігі тақырыбы файлы
class Truck { public: Truck(bool leaveOnDestruction = false); Truck(const Truck &other); Truck& operator=(const Truck &other); ~Truck(); void addIcecreamFlavor(Icecream *icecream); void printAvailableFlavors() const; bool deliver() const; void arrive() const; void leave() const; void setLeaveOnDestruction(bool value); void setArrivalMessage(const std::string &message); private: void clearFlavors(); bool m_leaveOnDestruction = false; std::string m_arrivalMessage = "A new icecream truck has arrived!\n"; std::vector m_flavors; };
Көптеген API интерфейстерін түсіну оңай болуы керек, бірақ біз маңызды бөліктерді қорытындылаймыз:
- Балмұздақ полиморфты түрі болып табылады және оны қайта анықтауға арналған
- getFlavor() нақты алынған түрге байланысты дәмді қайтарады
- Жүк көлігі өзіне тиесілі балмұздақ нысандарының векторын сақтайды, оны addIcecreamFlavor() арқылы қосуға болады.
- Жүк көлігінің келуі туралы хабарды setArrivalMessage() арқылы конфигурациялауға болады.
- deliver() бізге «балмұздақпен» жеткізу сәтті болды ма, жоқ па дейді
Шибокен типті жүйе
Shiboken-ті API туралы хабардар ету үшін бізге байланыстырулар қажет, ол үшін бізді қызықтыратын түрлерді қамтитын тақырып файлын жасаймыз:
#ifndef BINDINGS_H #define BINDINGS_H #include "icecream.h" #include "truck.h" #endif // BINDINGS_H
Сонымен қатар, shiboken C++ және Python түрлері арасындағы байланысты анықтайтын XML типтік жүйе файлын қажет етеді:
<?xml version="1.0"?> <typesystem package="Universe"> <primitive-type name="bool"/> <primitive-type name="std::string"/> <object-type name="Icecream"> <modify-function signature="clone()"> <modify-argument index="0"> <define-ownership owner="c++"/> </modify-argument> </modify-function> </object-type> <value-type name="Truck"> <modify-function signature="addIcecreamFlavor(Icecream*)"> <modify-argument index="1"> <define-ownership owner="c++"/> </modify-argument> </modify-function> </value-type> </typesystem>
Бірінші назар аударатын маңызды нәрсе, біз «bool» және «std::string» қарабайыр типтер ретінде жариялаймыз. Кейбір C++ әдістері оларды параметр/қайтару түрлері ретінде пайдаланады, сондықтан шибокен олар туралы білуі керек. Содан кейін ол C++ және Python арасында сәйкес түрлендіру кодын жасай алады.
C++ қарабайыр түрлерінің көпшілігі шибокен арқылы ешқандай қосымша кодты қажет етпестен өңделеді. Содан кейін біз жоғарыдағы екі сыныпты жариялаймыз. Олардың бірі «объект-тип» (объект-тип), екіншісі «мән түрі» (құндылық-объект) ретінде.
Негізгі айырмашылығы, «нысан түрі» құрылған кодта көрсеткіш ретінде беріледі, ал «мән түрі» көшіріледі (мән семантикасы).
Жүйе түрінің файлында сынып атауларын орнату арқылы shiboken автоматты түрде сыныптарда жарияланған барлық әдістер үшін байланыстыруларды жасауға әрекет жасайды, сондықтан барлық әдіс атауларын қолмен көрсетудің қажеті жоқ...
Мүмкіндікті қандай да бір жолмен өзгерткіңіз келмесе, бұл бізді келесі тақырыпқа, Иелік ережелеріне әкеледі.
Шибокен Python кодында орналастырылған C++ нысандарын босатуға кім жауапты екенін сиқырлы түрде таба алмайды.
Көптеген жағдайлар болуы мүмкін: Python нысанына сілтемелер саны нөлге тең болғанда Python C++ жадын босатуы керек немесе Python C++ нысанын C++ кітапханасының бір нүктесінде жойылады деп есептей отырып, ешқашан жоймауы керек. Немесе бұл басқа нысанның ата-анасы болуы мүмкін (мысалы, QWidgets сияқты). Біздің жағдайда clone() әдісі тек C++ кітапханасының ішінде шақырылады және біз C++ коды клондалған нысанның жадын босатуға қамқорлық жасайды деп есептейміз.
addIcecreamFlavor() функциясына келетін болсақ, біз Жүк машинасының Icecream нысанында тұратынын және Жүк көлігі жойылғаннан кейін бірден жойылатынын білеміз. Сонымен, иелік «c++» болып орнатылды.
Егер біз иелік ережелерін көрсетпесек, сәйкес Python атаулары қолданыс аясынан шыққанда C++ нысандары жойылатын еді.
Ассамблея
Теңшелетін Universe кітапханасын құру және одан кейін ол үшін байланыстыруларды жасау үшін біз жақсы құжатталған, негізінен жалпы CMakeLists.txt файлын береміз, оны өз кітапханаларыңыз үшін қайта пайдалануға болады.
Ол негізінен жобаны орнату үшін «cmake.» деп қоңырау шалумен аяқталады, содан кейін таңдаған құралдар тізбегімен құрастырыңыз («(N) Makefiles генераторын ұсынамыз).
Жобаны жасау нәтижесінде сіз екі ортақ кітапхана аласыз: libuniverse. (so/dylib/dll) және Әлем. (so/pyd).
Біріншісі - теңшелетін C++ кітапханасы және соңғысы Python сценарийінен импортталатын Python модулі (құжат, сынақ драйвері).
Әрине, shiboken арқылы жасалған аралық файлдар да бар (Python байланыстарын жасау үшін жасалған .h/.cpp файлдары). Ақаулықтарды жоюдың қажеті болмаса немесе қандай да бір себептермен ол компиляцияланбаған болса немесе қажетінше әрекет етпесе, олар туралы алаңдамаңыз. Содан кейін сіз Qt компаниясына қате туралы есеп бере аласыз!
Соңында біз Python бөлігіне жетеміз.
Python модулін пайдалану
Келесі шағын сценарийде біз Universe модулін қолданамыз, Icecream-тен мұра аламыз, виртуалды әдістерді енгіземіз, нысандарды жасаймыз және т.б.
from Universe import Icecream, Truck class VanillaChocolateIcecream(Icecream): def __init__(self, flavor=""): super(VanillaChocolateIcecream, self).__init__(flavor) def clone(self): return VanillaChocolateIcecream(self.getFlavor()) def getFlavor(self): return "vanilla sprinked with chocolate" class VanillaChocolateCherryIcecream(VanillaChocolateIcecream): def __init__(self, flavor=""): super(VanillaChocolateIcecream, self).__init__(flavor) def clone(self): return VanillaChocolateCherryIcecream(self.getFlavor()) def getFlavor(self): base_flavor = super(VanillaChocolateCherryIcecream, self).getFlavor() return base_flavor + " and a cherry" if __name__ == '__main__': leave_on_destruction = True truck = Truck(leave_on_destruction) flavors = ["vanilla", "chocolate", "strawberry"] for f in flavors: icecream = Icecream(f) truck.addIcecreamFlavor(icecream) truck.addIcecreamFlavor(VanillaChocolateIcecream()) truck.addIcecreamFlavor(VanillaChocolateCherryIcecream()) truck.arrive() truck.printAvailableFlavors() result = truck.deliver() if result: print("All the kids got some icecream!") else: print("Aww, someone didn't get the flavor they wanted...") if not result: special_truck = Truck(truck) del truck print("") special_truck.setArrivalMessage("A new SPECIAL icecream truck has arrived!\n") special_truck.arrive() special_truck.addIcecreamFlavor(Icecream("SPECIAL *magical* icecream")) special_truck.printAvailableFlavors() special_truck.deliver() print("Now everyone got the flavor they wanted!") special_truck.leave()
Модульден сыныптарды импорттағаннан кейін біз дәмдерімен теңшелген екі туынды (екінші) балмұздақ түрін жасаймыз.
Содан кейін біз жүк көлігін (жүк машинасын) жасаймыз, оған балмұздақтың (балмұздақтың) бірнеше қарапайым нұсқаларын (сорттарын) және екі арнайы нұсқаларды қосамыз.
Біз балмұздақ (балмұздақ) жіберуге (жеткізуге) тырысамыз.
Егер жеткізу сәтсіз болса, біз ескі нұсқалары көшірілген жаңа жүк көлігін және барлық тұтынушыларды қанағаттандыратын жаңа сиқырлы нұсқасын жасаймыз.
Жоғарыдағы сценарий C++ түріндегі қорытындыны пайдалануды, виртуалды әдістерді қайта анықтауды, нысандарды жасауды және жоюды және т.б. қысқаша көрсетеді.