« Guide du C++ pour .NET Programmation » : différence entre les versions

Contenu supprimé Contenu ajouté
Aucun résumé des modifications
(Aucune différence)

Version du 25 septembre 2005 à 18:45

< retour au sommaire

L'absence des char*

Les chaînes de caratères sont très utilisées en C++, mais inexistantes en .NET. Il existe pour cela la classe String, qui doit remplacer l'utilisation des char*. Des méthodes de conversion de l'un à l'autre sont donc disponibles, notamment grâce à la classe Marshal.

Ces méthodes étant abstaites, leur appel est assez pénible à tapper et surtout peu lisible, surtout si la tâche est très répétitive. Les paragraphes suivants proposeront donc de créer des MACROS pour rendre votre code bien plus lisible.

On notera que cela n'est faisable qu'en MC++, et pas en C# car ce dernier langage est dépourvu de macro. (en C# la classe Marshal est bien sur toujours utilisable).

Conversion des char* en String*

La méthode statique PtrToStringAnsi de la classe Marshal va réaliser la conversion d'un char * en String *. Le code suivant en est un exemple, (la valeur 256 correspond à la taille maximale de votre chaîne initiale, vous pouvez modifier ce paramètre):

using namespace System::Runtime::InteropServices;

char* ch_1 = "Hello World !";

String* ch_2 = Marshal::PtrToStringAnsi(IntPtr((void*) ch_1 ) , 256);

Il est fortement conseillé de créer une Macro dans un fichier header:

#define CONVERT2STRING(x)  Marshal::PtrToStringAnsi(IntPtr((void*) x ),256)

Ainsi l'utilisation de la classe Marshal est simplifiée

using namespace System::Runtime::InteropServices;

char* ch_1 = "Hello World !";

String* ch_2 = CONVERT2STRING(ch_1);


Conversion des String* en char*

De même, La méthode statique StringToHGlobalAnsi de la classe Marshal va réaliser la conversion d'un String * en char *. Cet appel nécessite une libération en utilisant la méthode FreeHGlobal.

using namespace System::Runtime::InteropServices;

String* s = new String("hello, World");

const char* temp = (const char*)(Marshal::StringToHGlobalAnsi(s).ToPointer());
...
Marshal::FreeHGlobal(IntPtr((void*)temp));

Les structures de données managées ou non

Les structures non managées sont du domaine du C++ classique, donc sans plate-forme .NET, et donc inaccessibles à partir de classes C#.

Les structures managées, quant à elles, sont des éléments qui pourront être accessibles.

Le C++ Managé permet une utilisation des deux types de structures de données. Il est donc nécessaire dans ce langage de déclarer explicitement qui est managé et qui ne l'est pas, grâce aux mots-clé __gc et __nogc.

Déclarer une classe __gc ou __nogc

Une classe managée sera déclarée ainsi:

public __gc class MaClasseManagee {
	...
}

De même pour une classe non managée:

public __nogc class MaClasseNonManagee {
	...
}

Déclarer un enum __gc ou ___nogc

De la même manière on déclare un type énuméré avec __gc pour managé et __nogc pour non managé:

public __gc enum Couleur = { ROUGE, ORANGE, VERT };

Déclarer un tableau __gc ou __nogc

De la même manière on déclare un tableau avec __gc pour managé et __nogc pour non managé:

public String __gc[3] CouleursList = { "Rouge", "Orange", "Vert" };

Les librairies managées ou non

L'ordre d'inclusion des librairies

Quelques ambiguïtés malheureuses peuvent apparaître si le principe suivant n'est pas respecté:

l'inclusion des fichiers header non managés est PRIORITAIRE

Sinon vous risquez de voir apparaître des erreurs au milieu de fichiers sources inconnus, dont la signification est incohérente.

Par exemple, un cas récurrent comme l'inclusion de "window.h" peut poser ce genre de problème.

Pour éclaircir votre code et éviter cette erreur, il est conseillé de créer un fichier header uniquement dédié à réaliser les inclusions dans le bon ordre.

Par exemple:

// inclusion_propre.h
#pragma once

// inclusions non managées
#include <cstring>
#include "la_vieille_bibliothèque.h"

// inclusions d'espaces de nom .NET
using System::Text;
using System::Runtime::InteopServices;

// inclusion de fichier Headers Managés

#include "mes_types_manage.h"
#include "mes_constantes.h"

Ainsi chaque fichier .cpp pourra inclure uniquement ce dernier fichier header, à condition que celui-ci soit toujours mis-à-jour.

Exemple:

// .cpp

#include "inclusion_propre.h"

MaClasseManagee::FonctionTresUtile() {
...
}


Pour plus d'information à propos de cette bizarrerie, voir le correspondant dans la MSDN