Delphi | FreePascal | MSW-Logo | PureBasic |
StarBasic (pour StarOffice) | Lotus Script (Pour Lotus Suite 97) | Python | C++Builder |
Excel et VisualBasic | |||
Autres logiciels difficiles à utiliser avec les DLL | Scilab | SmallBasic et YaBasic | PHP |
StarBasic (sans appel direct) | |||
UBasic | QBasic | TurboPascal | Matlab |
puis, dans la section exécutable, on donne un contenu à
ces fonctions :
@stdeadp:=nil;
@stdneadp:=nil;
@stdcalibration:=nil;
strpcopy(repchar,filename);
L:=loadlibrary(repchar);
@stdneadp:=getprocaddress(L,'stdnead');
@stdeadp:=getprocaddress(L,'stdead');
@stdcalibration:=getprocaddress(L,'stdcalibration');
éventuellement, on peut faire des tests pour savoir si la DLL
est utilisable :
if getprocaddress(L,'stdcalibration')<>nil
then reglages.enabled:=true
else reglages.enabled:=false;
if (@stdeadp<>nil)and(@stdneadp<>nil) then okpiloteP:=true
else okpiloteP:=false
Ensuite, les fonctions ainsi chargées pourront être utilisées normalement...
En principe, à la fin de l'utilisation de la librairie, par exemple lorsqu'on veut en charger une autre à sa place, il faut libérer la place par l'instruction FreeLibrary(L);
uses windows,sysutils,crt;
var l:thandle;
var repchar : array[0..80] of char;
var stdneap : function(n:integer):pchar;stdcall;
var stdneadp :function(n:integer):pchar;stdcall;
var stdeap : function(n:integer):integer;stdcall;
var stdeadp:function(n:integer):double;stdcall;
stdcalibration:function:integer;stdcall;
begin
clrscr;
@stdeadp:=nil;
@stdneadp:=nil;
@stdcalibration:=nil;
strpcopy(repchar,'c:\projd5\pourfp\xadesfp.dll');
L:=loadlibrary(repchar);
@stdneadp:=getprocaddress(L,'stdnead');
@stdeadp:=getprocaddress(L,'stdead');
@stdcalibration:=getprocaddress(L,'stdcalibration');
writeln(stdneadp(0));
writeln(stdeadp(0));
readln;
end.
(début de
page)
stddetailtype stddetail;
stdtitretype stdtitre;
stdeadtype stdstdead;
stdneadtype stdstdnead;
int a;
HINSTANCE handle=NULL;
char repchar[60];
String machaine;
puis on charge la librairie :
StrPCopy(repchar,"c:\\projd5\\xadestar.dll");
handle=LoadLibrary(repchar);
stddetail = (stddetailtype)GetProcAddress(handle,"stddetail");
stdtitre = (stdtitretype)GetProcAddress(handle,"stdtitre");
stdead = (stdeadtype)GetProcAddress(handle,"stdead");
stdnead = (stdneadtype)GetProcAddress(handle,"stdnead");
//Caption=stddetail();
//correct
Caption=stdtitre();//correct
//Caption=stdnead(0); //correct;
//Caption=String(stdead(0)); //correct;
et à la fin de l'utilisation, on peut libérer la mémoire
:
FreeLibrary(handle);
On peut ajouter quelques points très agréables :
- La version que je viens d'essayer (PureBasic 3.30) a les menus et
l'aide en français (ou en anglais, ou en allemand...)
- La syntaxe est automatiquement vérifiée et mise en
évidence lors de la frappe
Comme pour beaucoup de langages, il faut d'abord ouvrir la bibliothèque
par OpenLibrary.
Ensuite, on peut tester l'existence d'une fonction dans la bibliothèque
par IsFunction, mais ce n'est pas obligatoire.
Lorsqu'on veut utiliser une fonction, on l'appelle par CallFunction.
Pour les fonctions avec paramètres, il faut utiliser celles
qui sont compilées avec l'option stdcall (donc celles dont le nom
commence par std dans ma nomenclature).
Les fonctions qui renvoient un nombre sont utilisables sans difficultés
car CallFunction renvoie directement la valeur numérique correspondante.
Par contre, l'utilisation des fonctions qui renvoient une chaîne
est un peu plus délicate. L'appel de CallFunction renvoie l'adresse
de la chaîne en question, et il faut aller lire cette adresse par
la fonction PeekS, qui renvoie la valeur de la chaîne se trouvant
à l'endroit indiqué.
A la fin, on ferme la bibliothèque par CloseLibrary.
DefType .s machaine ; définit machaine comme une variable
de type chaîne (.s = "string")
If OpenLibrary(1,"c:\projd5\mgw32\pilotes\xadestar.dll")
*F2=IsFunction(1,"ead")
If *F2
monresultat=CallFunction(1,"stdead",0)
MessageRequester("message",Str(monresultat),2)
*value2=CallFunction(1,"stdnead",0);
machaine=PeekS(*value2)
MessageRequester("message",machaine,2)
EndIf
EndIf
CloseLibrary(1)
L'essentiel est correct : les fonctions travaillant avec des entiers
ou des chaînes de caractères sont utilisables, donc les fonctions
d'entrée et de sortie analogiques simples, ainsi que les fonctions
d'entrée et de sortie logiques et leurs noms sont correctes.
Tout n'est pas parfait quand même ! PureBasic ne travaille pas
avec des nombres réels de type «double», codés
sur 8 octets, mais sur des nombres de type «single», codés
sur 4 octets. Donc les fonctions stdead, stdsad et stdrsad ne sont pas
utilisables, ce qui est bien dommage !.
Que faire ? Rajouter des fonctions eas, sas, rsas («s»
comme «single») serait fastidieux s'il fallait le faire pour
les pilotes de tous les appareils, alors qu'apparemment, il n'y a que PureBasic
qui n'utilise pas les réels de type «double».
Une solution de rapport «efficacité/complication»
acceptable est la suivante : faire une dll spéciale (nommée
par exemple «xdll_double_single.dll») pour PureBasic, qui contient
ces fonctions de type «single», qui elle-même appelle
une dll normale, avec les valeurs de type «double». Pour que
toutes les dll normales soient utilisables, on peut convenir de recopier
systématiquement la dll de l'appareil de mesure à utiliser
dans un fichier nommé «xdll_purebasic.dll».
En consultant les développeurs de PureBasic, on m'a assuré
que l'utilisation des réels de type "double" était en pour
bientôt. Dès que ce sera fait, on pourra faire et utiliser
avec PureBasic les mêmes bibliothèques qu'avec les langages
Pascal et C++.
Symboles des types de paramètres et de résultats :
v = void (rien)
w = word (entier)
l = longword (entier long)
f = float (réel de type double)
s = string (spstr = chaîne de caractères à zéro
terminal)
Quelques remarques pour les habitués de Delphi :
- l'état majuscule/minuscule est important
- apparemment, pour les fonctions avec paramètres, il faut utiliser
les fonctions déclarées avec le mot stdcall, ou à
paramètres de type double.
- apparemment aussi, l'ordre des paramètres est inversé
par rapport à la déclaration en Delphi. Pour les fonctions
avec deux paramètres, il faut appeler d'abord le deuxième,
puis le premier.
- enfin, il semble qu'une seule DLL est chargeable à la fois.
Pour en utiliser une deuxième, il faut d'abord décharger
la première..
En résumé, pour faire une fonction «essai» qui affiche le nom de l'appareil, le nom de l'entrée analogique 0 et la valeur de cette entrée analogique, il suffit de faire dans l'éditeur :
to essai
dllload "c:/projd5/mgw32/pilotes/xdllvide.dll
print [nom_détaillé]
print dllcall[s detail]
print [nom de l'entrée analogique 0]
print dllcall[s stdnead w 0]
print [valeur ea 0]
print dllcall[f stdead w 0]
dllfree
end
puis de sauvegarder ceci, et de frapper «essai» dans la ligne de commande.
Python est un langage interprété, existant pour Windows comme pour Linux (et d'autres systèmes d'exploitation).Pour cela, elle charge les fonctions «stdnead» et «stdead»
dans la DLL nommée «xdll_python.dll».
En fait, «xdll_python.dll» peut être n'importe quelle
DLL du type décrit précédemment recopiée sous
ce nom. L'essai a été fait avec xades101.dll, pour le boitier
ADES.
library demodll;
{$I Definition.Inc}
uses
SysUtils,
Classes,
module in 'module.pas';
exports
initdemodll;
{$IFDEF MSWINDOWS}
{$E pyd}
{$ENDIF}
{$IFDEF LINUX}
{$SOPREFIX ''}
{$SONAME 'demodll'}
{$ENDIF}
begin
end.
Lorsqu'on compile demodll.dpr, le fichier compilé est renommé automatiquement demodll.pyd.
Pour utiliser les autres fonctions de la dll, il suffitde déclarer ces autres fonctions selon la même méthode dans le fichier module.pas.
Contenu du fichier «module.pas» modifié
unit module;
interface
uses PythonEngine,wintypes,sysutils;
procedure initdemodll; cdecl;
var
gEngine : TPythonEngine;
gModule : TPythonModule;
implementation
var dll_nead:function(n:integer):pchar;
var dll_ead:function(n:integer):double;
function Add( Self, Args : PPyObject ) : PPyObject; far; cdecl;
(*c'est la fonction d'exemple initiale*)
var
a, b : double;
begin
with GetPythonEngine do
begin
//syntaxe : d=double; i=integer
; s=string;
if PyArg_ParseTuple( args, 'dd:Add',
[@a, @b] ) <> 0 then
begin
Result :=
PyFloat_FromDouble( a + b );
end
else
Result := nil;
end;
end;
function stdead( Self, Args : PPyObject ) : PPyObject; far; cdecl;
var
a:integer;
begin
with GetPythonEngine do
begin
if PyArg_ParseTuple( args, 'i:stdead',
[@a] ) <> 0 then
begin
Result :=
PyFloat_FromDouble( dll_stdead(a) );
end
else
Result := nil;
end;
end;
function stdnead( Self, Args : PPyObject ) : PPyObject; far; cdecl;
var
a:integer;
begin
with GetPythonEngine do
begin
if PyArg_ParseTuple( args, 'i:stdnead',
[@a] ) <> 0 then
begin
Result :=
PyString_fromString(dll_stdnead(a));
end
else
Result := nil;
end;
end;
procedure initdemodll;
var l:thandle;
var repchar:array[0..100]of char;
begin
@dll_stdnead:=nil; @dll_stdead:=nil;
strpcopy(repchar,'c:\progra~1\python221\xdll_python.dll');
l:=loadlibrary(repchar);
@dll_stdnead:=getprocaddress(l,'stdnead');
@dll_stdead:=getprocaddress(l,'stdead');
try
gEngine := TPythonEngine.Create(nil);
gEngine.AutoFinalize := False;
gEngine.LoadDll;
gModule := TPythonModule.Create(nil);
gModule.Engine := gEngine;
gModule.ModuleName := 'demodll';
gModule.AddMethod( 'add', @Add, 'add(a,b) ->
a+b' );
gModule.AddMethod( 'stdead',@stdead,'stdead(a)
-> entrée analogique double');
gModule.AddMethod('stdnead',@stdnead,'stdnead(a)
->nom de l''entrée analogique');
gModule.Initialize;
except
end;
end;
initialization
finalization
gEngine.Free;
gModule.Free;
end.
Appel de la librairie «demodll.pyd»par Python
C'est très simple, il suffit d'entrer les commandes suivantes
:
from demodll import *
et les fonctions de la librairie deviennent disponibles.
Si l'on frappe :
print stdead(0), la valeur de l'entrée analogique 0
est affichée,
print stdnead(1), le nom de l'entrée analogique 1 est
affichée.
(début de
page)
Ensuite, dans le corps du programme en Basic, on utilise ces fonctions.
Note pour les habitués de Delphi : comme pour d'autres
logiciels, il faut tenir compte de la casse des noms des variables,
Si les fonctions sont compilées avec stdcall, l'ordre des paramètres
est le même que celui dans la déclaration dans Delphi ; par
contre, si les fonctions ne sont pas compilées avec stdcall, l'ordre
est inversé.
Le plus simple est de ne pas les déclarer avec stdcall ; si
l'on veut, on peut rajouter les fonctions stdeadouble, stdneadouble, etc...
Declare Function neadouble Lib "C:\projd5\mgw32\pilotes\xadestar.dll"
_
Alias "neadouble" (Byval n As Double) As String
Declare Function eadouble Lib "c:\projd5\mgw32\pilotes\xadestar.dll"
_
Alias "eadouble" (Byval n As Double) As Double
Declare Function stdsbdouble Lib "c:\projd5\mgw32\pilotes\xadestar.dll"
_
Alias "stdsbdouble" (Byval voie As Double , Byval valeur As Double
) As Double
Declare Function stdsb Lib "c:\projd5\mgw32\pilotes\xadestar.dll"
_
Alias "stdsb" (Byval voie As Integer , Byval valeur As Integer)
As Integer
Declare Function sbdouble Lib "c:\projd5\mgw32\pilotes\xadestar.dll"
_
Alias "sbdouble" (Byval voie As Double, Byval valeur As Double)
As Double
Declare Function sb Lib "c:\projd5\mgw32\pilotes\xadestar.dll" _
Alias "sb" (Byval voie As Integer, Byval valeur As Integer) As
Integer
Sub Click(Source As Buttoncontrol)
Messagebox Str$(stdsb(1,1)),MB_OK,"Demo"
End Sub
(début de
page)
Sub Module1
Declare Function stdead Lib "d:\dieumeg\xadestar.dll" (ByVal n
As Integer) As Double
Declare Function stdnead Lib "d:\dieumeg\xadestar.dll" (ByVal n
As Integer) As String
Sub MacroD()
Rem ' MacroD Macro
Rem ' Macro enregistrée le 31/01/03 par biologie
Rem '
Rem ' Touche de raccourci du clavier: Ctrl+Maj+D
Rem 'ActiveCell.FormulaR1C1 = "=RC[2]"
Rem 'Range("A2").Select
Rem 'ActiveCell.Value = stdnead(1)
Rem ActiveCell.Value = 55
Rem End Sub
Rem '
Rem ' MacroE Macro
Rem ' Macro enregistrée le 31/01/03 par biologie
Rem '
Rem ' Touche de raccourci du clavier: Ctrl+Maj+E
Rem '
Rem ActiveCell.Offset(-5, 4).Range("A1").Select
Rem ActiveCell.Value = 44
Rem ActiveCell.Value = stdnead(0)
Rem End Sub
Rem
End Sub
On peut donc imaginer de faire un petit programme (Delphi, C++ ou équivalent)
capable d'appeler les DLL et de faire les mesures, puis d'envoyer ces mesures
vers le logiciel principal.
(début de
page)
Un programme en Delphi pour Scilab, SmallBasic, Yabasic,
et autres logiciels pouvant récupérer directement les valeurs
program pdll32;
(*programme appelant une bibliothèque dynamique de mesure,
et envoyant le résultat
à l'écran : à utiliser avec les logiciels
interceptant les messages pour l'écran*)
(* conçu initialement pour Scilab*)
//p pour Print, imPrime...
{$APPTYPE CONSOLE}
uses
sysutils,wintypes;
var l:thandle;
var repchar:array[0..80] of char;
var nead:function(n:integer):pchar;
var ead:function(n:integer):double;
var stdead:function(n:integer):double;
stdcall;
var stdnead:function(n:integer):pchar;
stdcall;
var detail:function : pchar;
var chemindll,nomfonction,chparam1,chparam2:string;
var valparam1:double;
var valparam2:double;
var i:integer;
begin
chemindll:=paramstr(1);
nomfonction:=paramstr(2);
if paramcount>=3 then valparam1:=strtofloat(paramstr(3));
if paramcount>=4 then valparam2:=strtofloat(paramstr(4));
strpcopy(repchar,chemindll);
@nead:=nil; @ead:=nil;@stdead:=nil;@stdnead:=nil;@detail:=nil;
l:=loadlibrary(repchar);
@nead:=getprocaddress(L,'nead');
@ead:=getprocaddress(L,'ead');
@stdead:=getprocaddress(L,'stdead');
@stdnead:=getprocaddress(L,'stdnead');
@detail:=getprocaddress(L,'detail');
if nomfonction='ead' then writeln(ead(round(valparam1)):10:5);
if nomfonction='nead' then writeln(nead(round(valparam1)));
if nomfonction='stdead' then writeln(stdead(round(valparam1)):10:5);
if nomfonction='stdnead' then writeln(stdnead(round(valparam1)));
if nomfonction='detail' then writeln(detail);
freelibrary(L);
end.
Utilisation de ce programme par Scilab
Scilab est un logiciel de mathématiques, librement distribuable,
et réalisé par l'INRIA.
En fouillant dans la documentation en anglais, il semble capable d'être
lié à des bibliothèques extérieures, mais cette
documentation est très confuse.
En revanche, il peut lancer des logiciels extérieurs, et surtout
récupérer facilement le résultat.
L'instruction la plus intéressante est unix_g.
x=unix_g(commande)
lance la commande «commande» du système d'exploitation.
Cette commande peut être le nom du fichier à exécuter,
suivi éventuellement d'instructions en ligne de commande.
Le point le plus intéressant est que si cette commande doit
écrire à l'écran (du type writeln de Pascal),
ce qui devrait être écrit à l'écran est envoyé
vers la variable x.
Par exemple x= unix_g('dir') exécute la commande «dir»
du DOS, qui affiche la liste de tous les fichiers du répertoire
en cours ; x contient donc la liste de ces fichiers, que l'on pourra traiter
ensuite ...
x=unix_g('scidll32.exe xadestar.dll ead 0')
fait la mesure de l'entrée analogique 0 dans la bibliothèque
xadestar, et envoie le résultat de la mesure dans la variable x.
(début de
page)
Small Basic
SmallBasic est un langage Basic gratuit, réalisé par
Nicholas Christopoulos, et qui existe pour divers systèmes d'exploitation,
en particulier Windows et Linux, mais aussi PalmOS et d'autres.
L'instruction x=run(commande) envoie le résultat affichable
de la commande dans la variable x.
Par exemple, x=run("command.com /C dir *.exe") provoque l'envoi
dans la variable x d'un ensemble de chaînes de caractères,
résultat de la commande "dir *.exe ".
On peut donc utiliser cette instruction pour lancer un petit programme
de mesure, et récupérer le résultat, comme pour Scilab.
x=run("c:/mes documents/scilab/scidll32 xadestar.dll nead 1")
print x
(début de
page)
Yabasic
Yabasic est un petit langage Basic sans prétentions, d'origine
allemande, et fonctionnant avec divers systèmes d'exploitation :
Windows, Linux,... et même la console de jeux PS2, que je n'ai pas
essayée...
Il est téléchargeable en http://www.yabasic.de/yabasic.htm
L'instruction
a$=system$("dir *.exe /w ")
envoie dans la variable a$ l'ensemble de chaînes de caractères
correspondant à la commande dir *.exe /w.
En remplaçant cette commande par l'appel à un programme
de mesure, comme pour Scilab, on peut capturer le résultat de ce
programme.
PHP
Normalement, PHP est un langage de scripts pour les serveurs Web.
C'est le même principe, grâce à l'instruction system($commande),
qui effectue la commande correspondant au contenu de la chaîne de
caractère $commande.
Utilisation par Matlab
Le lancement du programme se fait en commençant la ligne par
le point d'exclamation :
!fdll32.exe xadestar.dll ead 1
Ensuite, il faut lire le fichier «fdll32.txt» par Matlab.
Si celui-ci contient une valeur numérique, par exemple renvoyée
par ead, il n'y a pas de problème : a=load('fdll32.txt')
envoie cette valeur dans la variable a.
C'est un peu plus délicat pour les chaînes de caractères,
par exemples celles renvoyées par «detail» ou par «nead».
Matlab est un logiciel conçu pour traiter les nombre, et beaucoup
moins pour traiter les chaînes de caractères.
Ceci se fait par l'instruction textread, qui a un grand nombre de possibilités,
assez confuses dans la documentation.
On peut proposer :
machaine=textread('fichres.txt','%c','whitespace','\t')'
Quelques explications :
l'instruction %c indique que l'on lit une chaîne de caractères.
«whitespace» et «\t» indique que le caractère
«espace» est la tabulation. Ceci peut paraître idiot,
car il n'y a pas de tabulation dans le fichier, et que les espaces sont
des vrais espaces entre les mots. Oui, mais si on ne met pas cette instruction,
les espaces disparaissent dans la chaîne finale.
Enfin, le caractère «'» final permet d'avoir une
chaîne en ligne, alors que lorsqu'on l'omet, la chaîne est
affichée en colonne. Ce n'est pas simple !
autres logiciels :
Python : à l'intérieur
du module os (il faut donc faire «from os import *»),
il y a les commandes :
- startfile, qui lance le logiciel qu'on lui passe en paramètre.
- system, qui lance la commande-système qu'on lui passe en paramètre.
Dans la pratique, pour Python pour Windows, le mieux est d'utiliser
les DLL grâce au système PythonForDelphi, et pour Python pour
Linux, d'utiliser les pilotes renvoyant directement le résultat
de la mesure.
StarOffice
Bien sûr, StarOffice pour Windows permet d'utiliser les DLL.
Mais il peut aussi lancer des fichiers extérieurs.
En frappant le sous-programme ci-dessous dans StarBasic, puis en associant
un bouton à ce sous-programme, on déclenche l'affichage d'une
fenêtre montrant la valeur de l'entrée analogique 1.
sub afficheead1
Dim iNumber As Integer
Dim aFile As String
dim sline as string
dim temps0 as long
rem dim commande$ as string
lignecommande$=dirdll$+"\fdll32.exe xdllvide.dll ead 1"
aFile = "fdll32.txt"
iNumber=Freefile rem ces trois lignes sont pour détruire
le fichier fdll32.txt, s'il existe
open aFile for output as #inumber
close #inumber
temps0=getsystemticks()
shell(lignecommande$,false)
while (filelen(afile)<2)and(getsystemticks()-temps0<1000)
wend rem cette boucle attend que fdll32.exe ait fait son
travail, fdll32.txt
iNumber = Freefile
Open aFile For input As #iNumber
Line Input #iNumber, sLine
close #inumber
msgbox(val(sline))
end sub
UBasic
GW-Basic (alias Basica) ne fonctionne plus sur les ordinateurs modernes.
Mais le langage Ubasic, de Mr Yuji KIDA, gagne à être connu
pour les nostalgiques : il a la même présentation que le vieux,
très vieux GW-Basic, mais a une puissance mathématique époustouflante,
et beaucoup plus de puissance générale.
Le miniprogramme suivant affiche simplement le résultat de «detail»
de la dll xdllrobot_com2.dll :
10 doscmd "fdll32.exe xdllrobot_com2.dll
detail"
20 open "fdll32.txt" for input as #1
30 input #1,Resultat$
35 close #1
40 print Resultat$
Qbasic
En un peu plus complexe, par exemple, voici un petit programme en Qbasic,
qui commande l'activation et l'extinction, à intervalles réguliers,
de la sortie analogique 0 de l'appareil correspondant à la bibliothèque
xdllrobot_com2.dll.
INPUT "Quelle est la durée de l'impulsion ?", dimp
INPUT "quelle est la durée du cycle ?", dcycl
tdepart = TIMER
eteint = 1
DO
position = (TIMER - tdepart) MOD dcycl
IF (eteint = 0) AND (position > dimp) THEN
SHELL ("fdll32.exe xdllrobot_com2.dll
sb 0 0")
eteint = 1
OPEN "fdll32.txt" FOR
INPUT AS #1
INPUT #1, reponse$
PRINT reponse$
CLOSE #1
END IF
IF (eteint = 1) AND (position <= dimp) THEN
SHELL ("fdll32.exe xdllrobot_com2.dll
sb 0 1")
eteint = 0
OPEN "fdll32.txt" FOR
INPUT AS #1
INPUT #1, reponse$
PRINT reponse$
CLOSE #1
END IF
LOOP UNTIL (TIMER - tdepart > 20)
TurboPascal 7
Ce programme fait la même opération que le précédent
en QBasic
program testedll;
uses dos,crt;
{$M $4000,0,0 } { 16K stack, no
heap }
const eteint:boolean=false;
var fich:text;
chainelue:string;
tdepart:real;
durimp,durcycle,position:longint;
function tsecondes:real;
var h,m,s,c:word;
begin
gettime(h,m,s,c);
tsecondes:=h*3600+m*60+s+c/100;
end;
begin
writeln('quelle est la durée d''une impulsion ?');
readln(durimp);
writeln('quelle est la durée d''un cycle ?');
readln(durcycle);
tdepart:=tsecondes;
assign(fich,'fdll32.txt');
repeat
position:=round((tsecondes-tdepart)) mod durcycle;
if (eteint and (position<durimp))
then begin
exec('fdll32.exe','xdllrobotcom2.dll
stdsb 0 1');
reset(fich);
read(fich,chainelue);
writeln(chainelue);
close(fich);
eteint:=false;
end;
if (not eteint)and(position>=durimp)
then begin
exec('fdll32.exe','xdllrobotcom2.dll
stdsb 0 0');
reset(fich);
read(fich,chainelue);
writeln(chainelue);
close(fich);
eteint:=true;
end;
until keypressed;
end.