Lost in the matrix

C/C++/C#/Java, Multithreading

#
# Usage : simple_cut <chaine> <separateur> <colonne>
#

simple_cut()
{
sep=`echo -e "\006"`
echo -n `echo -n $1 | tr "\n" $sep | tr $2 "\n" | head -n $3 | tail -n 1 | tr $sep "\n"`
}

using System.Reflection;
using System.IO;

namespace Tools
{
public static class PDATool
{
#region Property

public static string ApplicationDirectory
{
get
{
if (PDATool._Path == null) // On calcul la première fois le chemin.
PDATool._Path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().
GetName().CodeBase);
return (PDATool._Path);
}
}

#endregion

#region Attribut

// On conserve une le chemin pour éviter de le recalculer à chaque fois.
private static string _Path = null;

#endregion
}
}

#include <windows.h>

void getMemoryUsage(unsigned long *total,
unsigned long *avail,
float *usage,
unsigned long *virt_total,
unsigned long *virt_avail)
{
MEMORYSTATUSEX statex;

statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
if (total != NULL)
// mémoire physique totale
*total = (unsigned long)(statex.ullTotalPhys / 1024);
if (avail != NULL)
// mémoire physique disponible
*avail = (unsigned long)(statex.ullAvailPhys / 1024);
if (usage != NULL)
// pourcentage d'utilisation de la mémoire physique
*usage = (float)(statex.dwMemoryLoad);
if (virt_total != NULL) // mémoire virtuelle totale
*virt_total = (unsigned long)(statex.ullTotalVirtual / 1024);
if (virt_avail != NULL)
// mémoire virtuelle disponible
*virt_avail = (unsigned long)(statex.ullAvailVirtual / 1024);
}

#include <windows.h>

unsigned int getCPUcount(void)
{
SYSTEM_INFO sysinfo;

GetSystemInfo(&sysinfo);
return ((unsigned int)sysinfo.dwNumberOfProcessors);
}

Bonjour,

Voici le tout premier webcast, de la saga sur le multithreading.

video

Pour plus d'information sur le CSP, voir ici
Page Wikipédia de Sir Charles Antony Richard Hoare : ici

using System;
using System.CodeDom.Compiler;
using System.Diagnostics;

public class MicroCompiler
{
public MicroCompiler()
{
this.Language = "CSharp";
this.WarningLevel = 1;
this.OutputPath = "./~TMP.exe";
}

public bool Compile()
{
this.Result = string.Empty;
this.KillCompiledProgram();
using (CodeDomProvider codeProvider = CodeDomProvider.CreateProvider(this.Language))
{
// Paramètres de la compilation
CompilerParameters parameters = new CompilerParameters();
parameters.GenerateExecutable = true;
parameters.GenerateInMemory = false;
parameters.WarningLevel = this.WarningLevel;
parameters.OutputAssembly = this.OutputPath;
// on compile
CompilerResults results = codeProvider.CompileAssemblyFromSource(parameters,
new string[] { this.Source });
// est ce qu'il y a des erreurs ?
if (results.Errors.Count > 0)
{
foreach (CompilerError CompErr in results.Errors)
this.Result += "Line: " + CompErr.Line + " : " + CompErr.ErrorNumber +
" => " + CompErr.ErrorText + Environment.NewLine;
return (false);
}
}
// on créer le processus pour éxecuter le code
this.CompiledProgram = new Process();
this.CompiledProgram.StartInfo.FileName = this.OutputPath;
return (true);
}

public bool KillCompiledProgram()
{
if (this.CompiledProgram == null || this.CompiledProgram.HasExited)
return (false);
this.CompiledProgram.Kill();
return (true);
}

public bool StartCompiledProgram()
{
if (this.CompiledProgram == null)
return (false);
return (this.CompiledProgram.Start());
}

#region Properties

// Niveau d'avertissement.
public int WarningLevel { get; set; }

// Emplacement du programme généré
public string OutputPath { get; set; }

// Résultat de la compilation
public string Result { get; private set; }

// Le code source
public string Source { get; set; }

// Langage de la source (ex: CSharp)
public string Language { get; set; }

// Instance du programme en exécution.
public Process CompiledProgram { get; private set; }

#endregion
}

namespace Test
{
class Program
{
static void Main(string[] args)
{
MicroCompiler mc = new MicroCompiler();
mc.Source = "mettre le code C# ici!";
if (mc.Compile())
mc.StartCompiledProgram();
}
}
}

#include <windows.h>

int __stdcall FileExistsUnicode(wchar_t *fname)
{
return ((long)GetFileAttributesW(fname) > 0);
}

int __stdcall FileExistsAscii(char *fname)
{
return ((long)GetFileAttributesA(fname) > 0);
}

#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int copy_to_clipboard(char const *str)
{
HGLOBAL clipbuffer;
char *buffer;

// On ouvre le presse-papier
if (!OpenClipboard(NULL))
return (0);
// on vide le presse-papier
EmptyClipboard();
// on alloue la mémoire nécéssaire
clipbuffer = GlobalAlloc(GMEM_DDESHARE, strlen(str) + 1);
// on lock le buffer pour avoir un accès exclusif sur le presse-papier
if ((buffer = (char *)GlobalLock(clipbuffer)) == NULL)
{
GlobalUnlock(clipbuffer);
CloseClipboard();
return (0);
}
// On copie notre texte dans le presse-papier
strcpy(buffer, str);
// On déverouille le presse-papier
GlobalUnlock(clipbuffer);
// On met à jour le presse-papier
SetClipboardData(CF_TEXT, clipbuffer);
// On ferme le presse-papier
CloseClipboard();
return (1);
}

char *get_clipboard()
{
char *buffer;
HANDLE hData;

// On ouvre le presse-papier
if (!OpenClipboard(NULL))
return (NULL);
// On recupère le "handle" du presse-papier en mode texte
if ((hData = GetClipboardData(CF_TEXT)) == NULL)
return (NULL);
// On récupère via le "handle" le presse-papier
if ((buffer = (char *)GlobalLock(hData)) == NULL)
return (NULL);
// On déverouille le presse-papier
GlobalUnlock(hData);
// On ferme le presse-papier
CloseClipboard();
return (buffer);
}

int main(int argc, char **argv)
{
copy_to_clipboard("ma chaine");
printf("%s\n", get_clipboard());
getchar();
return (EXIT_SUCCESS);
}

Aujourd'hui nous allons voir comment embarquer une image dans une page HTML.
Pour cela nous avons besoin d'une image quelconque au format gif(ou autre chose),
d'un encodeur en base 64 et d'une minute.

1)allez sur le site : http://www.motobit.com/util/base64-decoder-encoder.asp.

2)Sélectionnez une image et encodez-la en base 64.

3)Créez une page HTML comme ci-dessous:

<html>
<head>
<title>Image embarquée</title>
</head>
<body>
<div style="text-align: center;">
<img SRC="data:image/gif;base64,"ALT="Mon image"/>
</div>
</body>
</html>

4)Insérez l'image encodée en base 64 après "base64,"

5)C'est fini!

/!\ Attention suivant les navigateurs l'image peut ne pas s'afficher!
Je déconseille par conséquent son utilisation, en production.

Le code ci-dessous affiche une petite étoile:
____________________________________________________________________________

<html>
<head>
<title>Image embarquée</title>
</head>
<body>
<div style="text-align: center;">
<img SRC="data:image/gif;base64,
R0lGODlhEAAQAOZIAP/HYf+kP//IY/HTvfGsTsvDvvKsTerKtP/Xr6RqSvzfmfro2P7fm/3TqfS1
e6dGDt6xlfKmSKNtTv7gnfWUNdZyINVxIP7Xg/y6aNV0I9t4JP3u4PbEheybTP759OuvfbRPDffK
odBsHfGxbfzhov7ajf7hkvebOuzLs9FxIv7UefvhydNzI/uaN/W1ZemPOffl1v7pof+xZKaXjvb2
9v/HYv7dhuvr6/7povPz89HR0e+SNcCGY/7Rb+Li4vn5+bl/XL5tPL2tpP7fpv7yvv+rRv+9WP+0
T////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5
BAEAAEgALAAAAAAQABAAAAengEiCg4SFhkgIMgiHhQ0YQxgNjIIeFApEChQehhsrIQ4uMTgxLg4h
KxuCCy8dIxwkJjYmJBwjHS8LSB8EFwwTJSo9KiUTDBcEH0gwFQYAAAICNdDOBhUwggMiEUbc3UYR
IgOEKCxH5udHLCiFBylF7/BFKQeFEBkBASc7J/gZEIQ5eGhoYQFEEBAWWmgA4uOHoBtCEjyQUABJ
AQkPEszQQWOSx4+DAgEAOw=="ALT="Mon image"/>
</div>
</body>
</html>

   Il arrive quelquefois que nous devions utiliser des composants
dont certaines parties sont devenues obsolètes avec le temps.
Malheureusement, il est parfois impossible (contrainte de temps
et/ou d'argent) de refaire le code en intégralité. Ainsi, la
plupart du temps nous en-capsulons les anciens composants dans
de nouveaux.

Seulement comment interdire l'accès aux propriétés obsolètes
de la classe de base et les remplacer par de nouvelles ?

En réalité c'est assez simple. Cette problématique a été résolue
Dans la version 2 du framework .Net. Il suffit d'utiliser l'attribut
"Obsolete" et de "override" certaines propriétés.

___________________________________________________________________

using System;

namespace Test
{
class A
{
// Rem: la class A peut toujours utiliser cette propriété.
public bool OldProperty { get; set; }
}

class B : A
{
// On indique au compilateur que la propriété est obsolète
[Obsolete("utilisez NewProperty à la place.", true)]
public new bool OldProperty { get; set; } // on "override" la propriété

public bool NewProperty { get; set; }
}

class Program
{
static void Main(string[] args)
{
B test = new B();
test.NewProperty = true; // OK
test.OldProperty = true; // Provoque une erreur à la compilation
}
}
}

   Jusqu'à la version 3.0, GCC utilisait la comparaison des noms
des symboles pour savoir si deux types étaient équivalent. Mais
depuis la nouvelle ABI (application binary interface) il ne compare
plus les noms, mais les adresses. Cela a pour but d'améliorer les performances.

Ce choix technique ne pose aucun problème avec un "linkage" statique,
car le les adresses sont déterminées et connues du compilateur.
Contrairement aux bibliothèques partagées (.dll, .so) qui
requièrent une résolution des types à l'exécution (runtime).

En effet si nous prenons en exemple une classe C qui
implémente deux interfaces I1 et I2 définies dans l'exécutable
et dans une bibliothèque partagée. Si nous essayions d'effectuer
un dynamic_cast sur une instance de C renvoyé par la bibliothèque
partagée en I1 ou I2, dynamic_cast renvoie toujours "null".
Le problème est aussi visible via throw et typeid.

Ce problème est dû au changement dans la résolution des types
énoncés ci-dessus. Pour corriger ce problème, il faut utiliser
l'option "-rdynamic" de GCC qui a pour but de créer une "global
symbol table" dans la bibliothèque partagée. Sous Linux/BSD le
compilateur réalise cette opération en passant l'option
"-export-dynamic" au "linker".

#include <unistd.h>

void my_print_hexa(int fd, unsigned int d)
{
if (d & ~0xF) /* si d > 16 */
my_print_hexa(fd, d >> 4); /* rec de d / 16 */
write(fd, (d & 0xF)["0123456789ABCDEF"], 1); /* tab + (d & 16) */
}

Dans cet article, nous allons étudier le framework JNI.
Ce framework Java permet d'exécuter du code non-managé
C/C++ dans du code Java.

Pour cette démonstration nous allons utiliser GCC 3.4.2(Win32)
et le JDK 6. Le code en C sera disponible dans une DLL.
Dev-CPP ou CodeBlocks conviennent parfaitement pour ce tutoriel.
____________________________________________________________________

1) Pour commencer nous allons créer une classe Java "Hello" avec
une methode native "Test" dans un fichier "Hello.java".

public class Hello
{
// Methode native qui correspond au prototype de la fonction
// qui sera appelé dans la DLL
public native void Test();

// Nous chargerons une DLL qui s'appelera "Hello.dll"
static
{
System.loadLibrary("Hello");
}
}

____________________________________________________________________

2) On compile la classe.

$>C:\Sun\SDK\jdk\bin\javac.exe Hello.java

____________________________________________________________________

3) On génère le fichier entête "Hello.h" pour la DLL.

$>C:\Sun\SDK\jdk\bin\javah.exe -jni Hello

#include <jni.h>
#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Hello
* Method: Test
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_Hello_Test(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

____________________________________________________________________

4) On implémente dans un fichier "Hello.c" notre fonction suivant
Le prototype définit dans "Hello.h"

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "Hello.h"

JNIEXPORT void JNICALL
Java_Hello_Test(JNIEnv *env, jobject obj)
{
printf("42\n");
}

____________________________________________________________________

5) On compile notre fichier source.

$>gcc -c -I"C:\Sun\SDK\jdk\include" \
-I"C:\Sun\SDK\jdk\include\win32" -o Hello.o Hello.c
____________________________________________________________________

6) On génère le fichier de définition de la DLL.

$>dlltool Hello.o -z Hello.def

Cela donne:

EXPORTS
Java_Hello_Test@8 @ 1

____________________________________________________________________

7) On Compile notre DLL.

$>gcc.exe -shared -o Hello.dll -I"C:\Sun\SDK\jdk\include" \
-I"C:\Sun\SDK\jdk\include\win32" Hello.c Hello.def


____________________________________________________________________

8) Nous allons maintenant créer un petit programme en Java pour
tester notre "wrapper" C vers Java dans un fichier "Main.java".


public class Main
{
public static void main(String[] args)
{
// Création d'une instance de notre classe "Hello"
Hello h = new Hello();
// On appel la fonction dans notre DLL (Hello.dll)
h.Test();
}

public Main()
{
super();
}
}

____________________________________________________________________

9) On Compile notre programme de test.

$>C:\Sun\SDK\jdk\bin\javac.exe Main.java

____________________________________________________________________

10) Il nous reste plus qu'à lancer le programme qui doit afficher
"42" sur la sortie standard suivi d'un retour à la ligne.

$>C:\Sun\SDK\jdk\bin\java.exe Main
$>42
$>

____________________________________________________________________

--- Le bug du UnsatisfiedLinkError ---

Il est possible qu'au moment où vous avez exécuter le programme
de l'étape 10, une erreur est apparue:


$>C:\Sun\SDK\jdk\bin\java.exe Main
$>Exception in thread "main" java.lang.UnsatisfiedLinkError: Init
$> at Hello.Test(Native Method)
$> at Main.main(Main.java:8)

Ce problème vient du fait que Java ne trouve pas le symbole de la
fonction "Test" dans notre DLL. Pour résoudre ce problème,
il nous faut revenir à l'étape 6. Dans le fichier "Hello.def"
où l'on peut lire les lignes ci-dessous:


EXPORTS
Java_Hello_Test@8 @ 1


Le problème vient des caractères que j'ai souligné en rouge.
Les noms des fonctions générées par les compilateurs ont toujours ces symboles.
La solution consiste à exporter les fonctions de la DLL sous un autre nom.
Pour cela il existe l'option -k de dlltool qui supprime les décorations
autour des fonctions. Par conséquent nous allons remplacer l'étape 6
par l'étape ci-dessous:

$>dlltool -k Hello.o -z Hello.def

Cela donne:

EXPORTS
Java_Hello_Test @ 1

Nous pouvons maintenant recompiler le projet qui fonctionne parfaitement.
---
Sous Microsoft Visual C, il faut utiliser le programme "dumpbin" afin
de récupérer les symbole de la DLL:

$>dumpbin Hello.dll /EXPORTS

Puis rajouter des directives pré-processeur #pragma pour chaque symbole
utilisé dans le fichier source ("Hello.c").

Exemple:

#pragma comment(linker, "/EXPORT:Java_Hello_Test=_Java_Hello_Test@8")

Voici une implémentation des varargs que j'ai fait dans
le train ce soir.
Elle n'est certes pas portable, mais elle
montre le principe de fonctionnement.
Idéal pour un cours de C.
_______________________________________________________________

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

# define Xva_list long *
# define Xva_start(L, X) (L) = (((Xva_list)(&(X))) + 1)
# define Xva_arg(L, T) (*(T *)(L++))

void test(int s, ...)
{
/* on déclare un pointeur pour stocker l'adresse dans la pile */
Xva_list list;

/* on récupère l'adresse de "s" que l'on décale de x octet */
/* x est égale a la taille en octet d'un pointeur. */
Xva_start(list, s);

/* on récupère nos arguments sur la pile */
printf("a = %d\n", Xva_arg(list, int));
printf("b = %c\n", Xva_arg(list, char));
printf("c = %s\n", Xva_arg(list, char *));
}

int main()
{
int a = 42;
char b = 'a';
char *c = strdup("chaine");

test(10, a, b, c);
free(c);
return (EXIT_SUCCESS);
}

Voici une méthode pour envoyer un évènement "KeyPress" à un
contrôle C#. Elle ne nécessite pas d'avoir le "focus" sur
l'élément visé.
---------------------------------------------------------------
using System;
using System.Windows.Forms;
using System.Reflection;

namespace Test
{
public sealed class KeyEventSender
{
private KeyEventSender()
{
}

// WM_CHAR est définit dans l'API de windows
// notification d'un événement clavier
internal static readonly int WM_CHAR = 258;

public static void Send(Control control, char c)
{
Message m = new Message();
m.HWnd = (IntPtr)control.Handle; // "Handle" du contrôle.
m.Msg = KeyEventSender.WM_CHAR; // type de l'évènement windows
m.LParam = IntPtr.Zero; // pas d'option
m.WParam = (IntPtr)c; // valeur de caractère
// on récupère la définition de la méthode par réflexion
// car la méthode n'est pas publique
MethodInfo dynMethod = control.GetType().GetMethod("ProcessKeyEventArgs",
BindingFlags.NonPublic BindingFlags.Instance);
// on invoque la méthode.
dynMethod.Invoke(control, new object[] { m });
}

public static void Send(Control control, KeyPressEventArgs e)
{
KeyEventSender.Send(control, e.KeyChar);
}
}
}