Utiliser une librairie C/C++ non managée dans un code c# (suite)

Comme nous avons pu le voir dans un article précédent, le wrapping de code C++ en C# peut être très simple, malheureusement les choses peuvent rapidement se compliquer !

En effet, continuons de travailler avec la dll GNU Scientific Library, et essayons d’utiliser une gls_matrix, la déclaration dans la documentation est la suivante :

typedef struct
{
    size_t size1;
    size_t size2;
    size_t tda;
    double * data;
    gsl_block * block;
    int owner;
} gsl_matrix;

La documentation nous explique aussi qu’un gls_block est la structure décrite ci dessous et que l’allocation d’une gsl matrix se fait via la fonction suivante :

typedef struct
{
    size_t size;
    double * data;
} gsl_block;

Function: gsl_matrix * gsl_matrix_alloc (size_t n1, size_t n2)

La première chose à faire est de déclarer une structure de type gsl_block en C#

[StructLayout(LayoutKind.Sequential)]
internal class gsl_block
{
    public uint size = 0;
    public IntPtr data = IntPtr.Zero;
}

On commence par déclarer un type struct et indiquer comment le ‘layout’ doit être effectué puis on déclare la class avec ses attributs. On peut constater la présence d’un type IntPrt , c’est la manière C# de gérer les pointeurs! (vue simplifiée mais bien pratique ^^). On peut maintenant déclarer le type gls_matrix comme suit !

    [StructLayout(LayoutKind.Sequential)]
    internal class gsl_vector
    {
        public uint size = 0;
        public uint stride = 0;
        public IntPtr data = IntPtr.Zero;
        public gsl_block block;
        public int owner = 0;
    }

Il ne reste maintenant plus qu’à compléter la fonction d’allocation gls_matrix_alloc. Là malheureusement il faut vraiment se plonger dans le code de la GSL pour trouver les sources et les adapter. En faisant ça on constate que l’on aura aussi besoin de la fonction gls_block_alloc. Le code des deux fonctions nécessaires sont si dessous :

        internal static gsl_block gsl_block_alloc(uint n)
        {
            gsl_block b = new gsl_block();
            b.data = Marshal.AllocCoTaskMem((int)n * sizeof(double));
            b.size = n;
            return b;
        }

        internal static gsl_matrix gsl_matrix_alloc(uint n1, uint n2)
        {
            gsl_matrix b = new gsl_matrix();
            b.size1 = n1;
            b.size2 = n2;
            b.tda = n2;
            b.block = gsl_block_alloc(n1 * n2);
            b.data = b.block.data;
            b.owner = 1;
            return b;
        }

Le point sensible l’implémentation est de bien comprendre ou est allouée la mémoire, en fait toutes les données sont stockées dans le gls_block c’est donc là qu’il faut alloquer la mémoire, le reste n’est qu’un jeu de pointeur. Bien sur une fois la matrice obtenu vous n’êtes pas encore au bout de vos peines, il faut maintenant coder les fonctions capables de libérer la mémoire allouée :

        internal static void gsl_block_free(gsl_block b)
        {
            if (b != null && b.data != null)
            {
                Marshal.FreeCoTaskMem(b.data);
                b.data = IntPtr.Zero;
            }
            b.size = 0;
        }
        internal static void gsl_matrix_free(gsl_matrix m)
        {
            if (m == null)
                return;
            gsl_block_free(m.block);
            m.block = null;
            m.data = IntPtr.Zero;
            m.size1 = 0;
            m.size2 = 0;
            m.tda = 0;
            m.owner = 0;
        }

Là encore, il faut libérer la mémoire marshallée dans la gsl_block, pour le reste on pourrait se contente de tout remettre à zéro. Dernière étape, allouer et récupérer des valeurs aux éléments de la matrice :

        [DllImport("libgsl.dll")]
        internal static extern void gsl_matrix_set(gsl_matrix m, uint i, uint j, double x);
        [DllImport("libgsl.dll")]
        internal static extern double gsl_matrix_get(gsl_matrix m, uint i, uint j);

Vous pouvez constater que cette fois je ne définis pas d’entry point dans la dll car le nom C# et le nom C++ sont identiques! Bien sur une gsl_matrix toute seule ne sert pas à grand chose, mais en ajoutant les fonctions de la GSL permettant de faire une décomposition de chloesky ou tout autre opération matricielle …

Problème SyntaxHighlighter et WordPress 2.7.1

Je suis, et comme beaucoup d’utilisateurs WordPress passé à la version 2.7.1 récemment et là, ô rage ô désespoir une erreur moche du type

Warning: htmlspecialchars_decode() expects parameter 1 to be string, NULL

surgissait à chaque fois que j’essayai d’insérer du code en utilisant le plugin SyntaxHighlighter ! Heureusement , des gens intelligents se sont penchés sur la question et il existe une solution pas très compliquée ce problème :

There is a variable name mismatch in the WordPress version of the function htmlspecialchars_decode (introduced in PHP5.1). Parameter 1 is $str, but the validation tests $string, and thus the function will never execute, because $string is always null and fails the test.

This is a regression because it broke the AZIndex plugin (version 0.7.5) when the « ignore characters » option was set for an index. It will also break any code, plugin, or theme that uses this function when running on PHP < 5.1.

The line in error is line 104 in wp-includes/compat.php:

if ( !is_scalar( $string ) ) {

should be

if ( !is_scalar( $str ) ) {

Il suffit donc de remplacer $string par $str à l’endroit indiqué (tant qu’a fait à la ligne suivante vous pouvez aussi faire la modification !) et tout refonctionnera bien, testé et approuvé 🙂

Version originale de la solution : ici !

Création d'une base SQLServer Compact Edition en C#

Des fois certains programmes nécessitent des bases de données qui ne contiendront pas des terras de données, qui ne doivent pas traiter 10 000 000 de tuples à la secondes et qui surtout doivent être légères et faciles d’utilisation ! SQL Server Compact Edition n’est pas un candidat évident de par sa naissance : destiné de base aux applications pour systèmes embarqués (téléphones mobiles, PDA..) un programmeur classique ne pensera pas forcément à l’utiliser dans une de ses applications …. et pourtant les avantages sont multiples !

  • La légèreté est le premier avantage :  Il suffit d’ajouter une référence à son projet C# : System.Data.SqlServerCE et une bonne partie du travail est fait.
  • Lors du déploiement de l’application pas d’installation supplémentaires (types une base mysql…)
  • Création de fichiers (*.sdf) facilement lisibles, modifiables, voir même commitables sur svn (finit les dump !)
  • j’en passe !

Évidement il ne faudrait pas non plus oublier les défauts de SqlServerCE :

  • Technologie Microsoft (ce qui n’est pas un défaut en soit mais limite la portabilité … évidement quand on code en C# ce n’est pas forcément ce que l’on recherche le plus :))
  • Performances bien inférieures à des bases “pro” type SqlServer, Mysql5 ou oracle 9
  • Limitation de taille à 4 Go
  • j’en passe aussi !

Vous l’aurez compris, son utilisation n’est pas à généraliser mais dans des cas précis (application de traitement de statistiques sur quelques millions de données, gestion de configurations par stockage en base …) l’utilisation peut valoir le détour. Comment faire alors ? Comme avec beaucoup d’outils maintenant on peut faire çà “à la souris” en utilisant Visual Studio 2008 … Ce n’est pas vraiment ce que j’aime fait, préférant comprendre ce qui se passe plutôt que faire des drag & drop (oui parce que le jour ou le bouton change de place on à pas l’air malin :)) Bref, une créons une base dont le fichier source sera ref.sdf , commençons par vérifier si on peut le créer !

Bref, une créons une base dont le fichier source sera ref.sdf , commençons par vérifier si on peut le créer !


if (System.IO.File.Exists(&quot;ref.sdf&quot;)){
System.IO.File.Delete(&quot;ref.sdf&quot;);}

Maintenant que la place est libre, créons notre base, pour cela utilisons les appels suivants:


String str = “Data Source = ref.sdf; Max Database Size = 4000;”
SqlCeEngine engine = new SqlCeEngine(str);
engine.CreateDatabase();
engine.Dispose();

Dans la création string (str) on peut rajouter d’autres paramètres, tel un password … le Database Size ne représente pas la place réservée par le fichier mais la taille maximale autorisée pour le fichier base. Évidement sur un PC classique ça peut sembler étrange mais rappelez vous que SqlServerCE est avant tout utile pour les applications mobiles ! Maintenant la base est créée mais elle est vide, il faut donc s’y connecter puis créer une table.


private SqlCeConnection myConnection = null;

//Connexion à la base de données

try {
myConnection = new SqlCeConnection(“Data Source = C:\\Documents and Settings\\Nicolas\\Mes documents\\ref.sdf;”);
myConnection.Open();
}catch (Exception e) {
Console.WriteLine(“Erreur lors de la connection a la base de donnees. Message d’erreur:”);
Console.WriteLine(e.Message);
throw (e);
}

//Création des tables si on passe ici, il n’y a pas eu de throw -&gt; pas de test sur myConnection

SqlCeCommand cmd = myConnection.CreateCommand();

string s =

“CREATE TABLE  test (Date datetime, ”Cotation float, Rendement float, Primary Key (Date))”;
cmd.CommandText = s;

//Exécution de la requête.
try{
cmd.ExecuteNonQuery();
}catch (Exception e){
Exception f = new Exception(“Erreur lors de la creation de la table: ” + e.Message);
throw (f);
}

Vous disposez maintenant d’une base enregistrée dans le fichier ref.sdf, la base contient une table ‘test’ qui à 3 attributs : Date de type timedate et qui est la clé primaire de la table, Rendement et Cotation qui sont de type float.

Dans un prochain article des informations sur l’insertion / la récupération de données dans une base sql!