C++/CLI

C++ Express: compatibilità, terminazioni di linea e codifica Unicode

Nelle ultime settimane mi sono imbattuto in tre features di Visual C++ Express. Sono caratteristiche poco "appariscenti", sulle quali sarebbe sprecato fare marketing, ma che si sono rivelate particolarmente utili. 1. E' possibile aprire vecchi progetti per Visual C++ 6. La procedura di conversione è pressochè indolore. Naturalmente, a causa degli allineamenti agli standard C++, è possibile che il nuovo compilatore generi messaggi di avviso, indicando che vengono usati costrutti sintattici deprecati. 2. Durante l'apertura di un file, l'editor rileva automaticamente se la convenzione di terminazione linea è consistente e, in caso contrario, propone un allineamento con lo standard per Windows, Unix o Macintosh. 3. Per impostazione definita i file...

posted @ giovedì 24 novembre 2005 16:33 | Feedback (0)

Cleanup deterministico e finalizers in C++/CLI

Vediamo il seguente codice. Viene definito un reference type (typeid = Person), con un metodo publico, ReadMessage. Al suo interno viene utilizzato in tre modi diversi un oggetto di tipo System::IO::StreamReader, classe che implementa System::IDisposable. public ref class Person{public:    Person (String^ name, String^ surname)    {    }    void ReadMessage (String^ path)    {        Stream^ stream = (Person::typeid)->Assembly->GetManifestResourceStream (path);#ifdef MANUAL_DETERMINISTIC_CLEANUP        // I manually call the distructor.        StreamReader^ reader = gcnew StreamReader (stream);        Console::WriteLine (reader->ReadLine ());        delete reader;#endif#ifdef AUTOMATIC_CLEANUP        // Garabace collector will call the dispose methods before finalizing the reader.        StreamReader^ reader = gcnew StreamReader (stream);        Console::WriteLine (reader->ReadLine ());#endif#ifdef AUTOMATIC_DETERMINISTIC_CLEANUP        // The compiler automatic inserts a method call to dispose.        // The reference type instance has value semantic in this context.        StreamReader reader (stream);        Console::WriteLine (reader.ReadLine ());#endif    }}; Decompiliamo con Reflector e vediamo come apparirebbe, nei diversi casi, il metodo ReadMessage se fosse scritto in C#. Nel primo caso reader è stato dichiarato come un handle, al quale abbiamo è stato assegnato un oggetto allocato sul managed heap tramite l'operatore gcnew . Dopo essere stato utilizzato, l'oggetto viene "distrutto" con l'operatore delete. Tale operatore viene sostanzialmente ...

posted @ venerdì 6 maggio 2005 02:05 | Feedback (0)

Visual C++ 2005 and *.vcproj

Se state usando Visual C++ 2005, vi sarete probabilmente accorti che l'ambiente non è ancora del tutto completo. Esistono alcune limitazioni nella gestione del progetto (file di risorsa, file di soluzione, etc.). Non so se queste rimarranno limitazioni del prodotto Express definitivo, ad ogni modo potete ovviare a questi problemi scrivendo manualmente il file di progetto e vcbuild.exe per compilarlo. Qui potete trovate lo schema XML: http://msdn2.microsoft.com/library/y4sy8216(en-us,vs.80).aspx Il designer è decisamente migliorato, tuttavia, a mio parere, genera un pessimo codice. Sarebbe stato importante, per lo meno, che separasse le implementazioni dei metodi (in particolare, del costruttore e dei delegati che gestiscono gli eventi) dalla...

posted @ mercoledì 20 aprile 2005 12:37 | Feedback (3)

Prova sinstassi C++/CLI

Ho scritto un file per il syntax highlighting di Code Snippet Editor destinato al nuovo linguaggio C++/CLI. Come vi sembrano i colori? Sicuramente non è perfetto ma per iniziare può andare bene. A proposito... se non conoscete le novita del nuovo linguaggio che sarà rilasciato con Whidbey, date un'occhiata al codice. Presto scriverò un articolo in merito... Credo che il mio rapporto con C# stia per finire... dopo soli 3 mesi... Ecco un piccolo esempio (non mostra proprio tutti tutti i costrutti... ma non volevo esagerare). PS Scusate, lo riposto scrollabile perchè mi sembrava un po' da cafoni occupare tutta la pagina dei nuovi post #using <mscorlib.dll>#using <System.dll>#pragma managedusing namespace System;namespace Example {        /* Customer data. * Inherits from System::ValueType. */public value struct CustomerKey: IComparable<CustomerKey^>{    public:        CustomerKey (String^ firstName, String^ lastName):        FirstName (firstName),        LastName (lastName)    {    }        String^ FirstName;    String^ LastName;    bool Equals (CustomerKey^ key) override    {        bool firstNameResult = this->FirstName->Equals (key->FirstName);        bool lastNameResult = this->LastName->Equals (key->LastName);        return (firstNameResult && lastNameResult);    }    int CompareTo (CustomerKey^ key) override    {        return Equals (key);    }    };/* Customer. * Inherits from System::Object. */public ref class Customer{private:    initonly CustomerKey key_;    public:    Customer (CustomerKey % key)    {        key_ = key;    }    Customer (String^ firstName, String^ lastName)    {        if (firstName == nullptr) throw gcnew ArgumentNullException ();        if (lastName == nullptr) throw gcnew ArgumentNullException ();        key_ = CustomerKey (firstName, lastName);    }    property CustomerKey^ Key    {        CustomerKey^ get () { return key_; }    }    property String^ FirstName    {        String^ get () { return key_.FirstName; }    }        property String^ LastName    {        String^ get () { return key_.LastName; }    }    String^ ToString () override    {        String^ s = key_.FirstName;        return s;    }};typedef System::Collections::Generic:ictionary<CustomerKey^, Customer^> CustomerDictionary;typedef System:iagnostics:ebug Debug;public ref class CustomerContainer {    CustomerDictionary^ customers_;public:    CustomerContainer ()    {        customers_ = gcnew CustomerDictionary ();    }        void Insert (String^ firstName, String^ lastName)    {        try         {            Customer^ customer = gcnew Customer (firstName, lastName);            customers_->Add (customer->Key, customer);            Debug::WriteLine ("Inserted: %s", customer->ToString ());        }        catch (Exception^ exception)        {            Debug::WriteLine (exception->Message);            throw;        }    }};}using namespace Example;/* Entry point of the application. * It should be in the default namespace! */int main () {        String^ helloWorld = "Hello world!";    CustomerContainer^ container = gcnew CustomerContainer ();    container->Insert ("Andrea", "Sansottera");        return 0;}

posted @ venerdì 25 febbraio 2005 20:53 | Feedback (8)