V tomto článku porovnávám Objective-C++ a C++/CLI, dva hybridní jazyky vzniknuvší „sloučením“ dvou zavedených jazyků. V prvním případě jde o Smalltalk a C++, ve druhém případě o C++ a C# (zjednodušeně řečeno, viz níže).
Objective-C++
Brad Cox a Tom Love vytvořili jazyk Objective-C jako objektově-orientované rozšíření (inspirované Smalltalkem) jazyka C. Původní kompilátor byl jen jakýmsi preprocesorem, jenž kód v Objective-C převedl do jazyka C (podobně jako tomu bylo v počátcích u C++). Deklarovaným cílem bylo vytvořit moderní jazyk (OO bylo tehdy podobnou módou jako dnes např. HTML5), ve kterém by ovšem bylo možné používat knihovny napsané v jazyce C. Objective-C++ je založené na stejném principu, ale je nadstavbou jazyka C++.
S jazykem Objective-C(++) se dnes setkáte nejspíše při programování pro Mac OS X a iOS. Pro Objective-C je k dispozici rozsáhlá knihovna, ale občas potřebujete použít v kódu cizí knihovnu napsanou v C nebo C++. Jako příklad mějme třídu Translator, která implementuje strojový překlad z angličtiny do češtiny (ne pomocí Google Translate, ale nativně; takový kód opravdu existuje v rámci projektu Apertium). Použití je následující:
Translator t = new Translator("en", "cs");
std::string s = t.translate("Hello, world!"); // vrátí "Ahoj, světe!"
Nyní si představme, že chceme kód z Apertia použít v aplikaci pro Mac OS X nebo iOS. Standardním postupem je implementovat tzv. wrapper, tj. třídu v Objective-C, která vývojáře odstíní od nízkoúrovňového kódu v C nebo C++. V našem případě se nabízí vytvořit třídu APTranslator (prefix AP znamená Apertium), jež poskytne rozhraní pro použití knihovny. Toto rozhraní by mohlo vypada nějak takto:
@interface APTranslator : NSObject {
Translator* translator;
}
- (NSString*)translateString:(NSString*)text;
@end
Je zřejmé, že kromě vytvoření instance třídy Translator (což je triviální) musíme zajistit převod mezi NSString* a std::string. K tomu naštěstí můžeme využít metod, které nabízí třída NSString. Metoda translateString:
by pak vypadala takto:
- (NSString*)translateString:(NSString*)text {
std::string s = [text UTF8String];
s = translator->translate(s);
return [NSString stringWithUTF8String: s.c_str()];
}
Pochopitelně je nutné implementovat také metody init
a dealloc
pro vytvoření a uvolnění instance třídy Translator. Tím jsme hotovi a můžeme třídu ATTranslator používat:
ATTranslator* translator = [[ATTranslator alloc] init];
NSLog(@"%@", [translator translateText: @"Hello, world!"]);
C++/CLI
Když Microsoft vytvořil platformu .NET, zveřejnil také zcela nový jazyk: C#. Pro .NET je ovšem možné programovat i v jiných jazycích, a tak kromě Basicu (ve verzi Visual Basic .NET) můžeme psát pro .NET také v C++, resp. jeho rozšíření, které se nazývá C++/CLI. Podobně jako u Objective-C(++) je C++/CLI nadstavbou jazyka C++ a účelem tohoto jazyka je umožnit použití knihoven napsaných v C a C++ v aplikacích pro .NET (typicky se taková nativni knihovna „zabalí“ do dynamické knihovny, tedy souboru s příponou .dll, kterou lze pak přímo použít v C#).
Na stejném příkladu jako výše pro Objective-C++ si ukážeme, jak by vypadal stejný „wrapper“ v C++/CLI. Jediným větším problémem je zajistit převod mezi nativním řetězcem (std::string) a řetězcem v .NET (String^). K tomu použijeme funkci marshal_as ze jmenného prostoru msclr::interop.
public ref class APTranslator {
private:
Translator* translator;
public:
APTranslator() { translator = new Translator("en", "cs"); }
String^ translate(String^ text) {
std::string s = marshal_as<std::string>(text);
s = translator->translate(s);
return marshal_as<String^>(s);
}
};
Použití je pak už jednoduché:
(gcnew APTranslator("en", "cs"))->translate("Hello, world!")
Pochopitelně ještě musíme uvolnit instanci třídy Translator při zániku „wrapperu“.
Poznámku si zaslouží překlad kódu v C++/CLI. K dispozici jsou tři varianty: /clr:safe, /clr:pure a /clr. První z nich generuje tzv. bezpečný kód, který je ekvivalentní výsledku překladu kódu v C#. Problém je, že v takovém kódu nelze použít nativní kod v C/C++, čímž tato volba ztrácí smysl, protože pro čistý kód pro .NET je pak už stejně lepší psát v C#. Volba /clr umožňuje míchat téměř libovolně nativní kód s knihovnami .NET. Nativní kód je ale překládán přímo do kódu procesoru, čímž se připravujeme o cennou kompatibilitu výsledného spustitelného souboru. Nejlepší volbou je proto pro většinu aplikací volba /clr:pure, která také umožňuje použít nativní kód (včetně např. knihovny STL), ale kompiluje do mezikódu CLR, takže přeložený program lze spustit všude, kde je k dispozici .NET framework. I tato volba má jistá omezení vzhledem k nativnímu kódu, ale většinu knihoven takto přeložit lze.
Bohulibé náměty článků, ale obávám se, že texty jsou hodně stručné. Kdybych se chtěl dozvědět, jak funguje Objective-C(++) a k čemu je jazyk dobrý, chtělo by to asi samostatný, delší, článek. V úvodu je navíc slibováno jakési porovnání, ale nevím, jaký závěr si z tohoto "porovnání" mám vzít. Nechci rýpat, ber to jako dobře myšlený názor čtenáře.
Autor se zabývá vývojem kompilátorů a knihoven pro objektově-orientované programovací jazyky.
Přečteno 36 207×
Přečteno 25 364×
Přečteno 23 797×
Přečteno 20 180×
Přečteno 17 876×