De C# à C++ : quelques trucs simples en C# que je ne retrouvais pas en C++

 

Lorsque l’on fait du C# depuis quelques années on commence à prendre quelques habitudes et on pense que c’est tout cuit tout le temps. Sauf que lorsque l’on passe en C++ on se rends compte que .Net  nous facilite quand même bien la vie. Prenons donc aujourd’hui quelques exemples qui vous feront peut être gagner du temps.

 

Ecrire quelque chose dans la fenêtre d’Ouput en Debug

Facile, il suffit de faire Debug.WriteLine()… sauf que non :p ! Je me sers encore assez souvent de la fenêtre d’Output pour écrire des informations de Debug. Ce n’est pas forcément nécessaire car VisualStudio permet de le faire via des breakpoints mais que voulez-vous, j’aime coder :) !

En C++, il existe une macro toute simple à utiliser, elle se situe dans le header windows.h et se nomme OutputDebugString(). Attention de bien inclure le saut à la ligne à la fin si nécessaire.

#include <Windows.h>
OutputDebugString(L"Sarah Connor ?\n");

 

Transformer un int/long en (w)string

En C# c’est tout simple, on a la petite méthode ToString (héritée d’Object) sur chaque objet et au pire on peut aussi concaténer une chaine de caractère avec un int en utilisant l’opérateur “+”. Faisons la même chose en C++ :

OutputDebugString(L"Non c'est à côté : "+ 42);

 

Et bien cela va afficher quelque chose entre tout et n’importe quoi (plus proche du n’importe quoi que du tout d’ailleurs). Pourquoi donc ? Tout simplement car vous demander en réalité d’afficher la chaine de caractère située à la position de "Non c'est à côté : " mais décalé de 3 bytes. OutputDebugString prends un pointeur vers une chaine de caractères et vous lui en donner un décalé de votre int. Cela ne peut donc pas marcher.

Heureusement pour nous, il existe dans le header “string.h” une méthode to string qu’il suffit d’appeler comme suit :

#include <string>

auto monIntEnString = std::to_wstring(42);

 

Concaténer 2 chaines de caractères (dans OutputDebugString)

Pour concaténer deux chaines de caractères, il y a l’opérateur + comme en C#. Cependant lorsque je l’utiliser comme ça avec OutputDebugString cela ne veux pas compiler :

OutputDebugString(L"Youpi : " + std::to_wstring(3));

En effet, l’opérateur ne retourne pas le bon type attendu (CONST WCHAR *). La solution consiste à utiliser l’helper c_str pour produire ce bon type à partir de la chaine originale :

OutputDebugString((L"Ce ne sont pas les char que tu recherches : " + std::to_wstring(3)).c_str());

DateTime.Now

Il est souvent pratique de connaitre l’heure actuelle (d’ailleurs Julien nous a dernièrement donné des astuces sur les manipulations de date). Cela permet notamment de savoir si c’est bientôt le week end. Cela me permet souvent d’avoir un timestamp pour ordonnancer différentes tâches. La manière la plus simple que j’ai trouvé (mais je sais qu’il y en a pleins d’autres) est d’utiliser la méthode GetSystemTimeAsFileTime qui retourne l’heure et la date UTC courante. Cette méthode est définie dans le fichier d’header “Windows.h”. Il faut lui fournir en paramètre une référence vers une structure FILETIME qui va alors être remplie. On peut alors utiliser cette structure pour obtenir un ULONG correspondant à la date :

inline const ULONG getInt64Now(){

    FILETIME now;
    GetSystemTimeAsFileTime(&now);

    ULARGE_INTEGER largetInteger;
    largetInteger.HighPart = now.dwHighDateTime;
    largetInteger.LowPart = now.dwLowDateTime;

    return largetInteger.QuadPart;
}

Cette valeur peut alors être comparée à la propriété “Duration” d’un TimeSpan WinRT.

 

Thread.Sleep et Task.Yield()

En C# j’ai souvent l’habitude d’utiliser Task.Delay() pour attendre un certain temps avant une action ou pour simuler de la latence lorsque j’optimise une application. C’est très simple à appeler et il existe une méthode quasi similaire en utilisant les tasks de la PPL : concurrency:::wait(). Attention de ne pas confondre la méthode homonyme sur les tasks, je parle de la méthode statique “wait” du namespace concurrency.

Cette méthode prend en paramètre un long correspondant au nombres de millisecondes à mettre en pause le contexte courant. Cette durée n’est pas précise et peut être plus longue mais on n’a pas toujours besoin de cette précision. Si vous indiquez la valeur “0” pour ce paramètre vous retrouvez alors la méthode Task.Yield tellement utile dans certaines situations.

Attention cependant de n’utiliser cette méthode que dans le cas d’une task ou dans une application console et surtout pas sur le Thread UI de votre application Windows 8 sinon : crash ! Pour ces cas, il faut utiliser WaitForSingleObject.

Nous allons dans cet exemple rendre hommage aux milliers de koalas morts dignement pour défendre l’intégrité de C++ fasse aux exactions (encore récemment décrites par Simon) commises par les “undefined behaviors” en effectuant 10 secondes de silence :

//Faisons dix secondes de silence en l'hommage des koalas.
concurrency::wait(1000*10);

//Task.Yield est parmi nous !
concurrency::wait(0);

 

Voila, j’espère que cet article vous a plu et vous fera gagner un peu de temps :) !

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus