I. Introduction ♪▲
La présente note technique permet de manipuler des données avec les librairies 4D Open et d'effectuer des traitements concernant les suppressions et ajouts de données, le tri et la recherche d'informations ainsi que la manipulation des ensembles et des Blobs.
Le Client 4D Open généré va réaliser les opérations suivantes :
- suppression et Ajout d'enregistrements ;
- recherche d'enregistrements ;
- tri des sélections d'enregistrements ;
- manipulation d'ensembles ;
- manipulation de Blobs.
II. Organigramme des opérations qui peuvent être réalisées par les librairies « 4D open »▲
Vous trouverez ci-dessous un résumé de tout ce que vous pouvez faire avec les librairies « 4D Open » :
Phase 1▲
Elle correspond aux différents traitements qui peuvent être réalisés sur le 4D Server :
- chercher et trier ;
- créer des sélections nommées ;
- ajouter, modifier et supprimer des enregistrements ;
- afficher utilisateurs et groupes ;
- afficher des informations sur les process, etc.
Phase 2▲
Elle correspond aux connexions qui peuvent être ouvertes sur le même 4D Server. Avec les librairies « 4D Open », nous pouvons ouvrir plusieurs connexions sur le même 4D Server.
Phase 3▲
Elle correspond aux connexions simultanées avec plusieurs 4D Server. Avec les librairies « 4D open », nous pouvons ouvrir un ou plusieurs 4D Server simultanément.
Phase 4▲
Elle correspond au protocole utilisé avec 4D open, seul le protocole TCP peut être utilisé avec les librairies « 4D Open ».
III. Explication des points d'entrées de l'API utilisés dans le code source « C »▲
Supprimer et ajouter des enregistrements▲
Avant d'ajouter de nouveaux enregistrements, nous allons supprimer les enregistrements existants dans la base de données, nous utiliserons pour cela les routines suivantes :
_4D_SelectAllRecords
_4D_DeleteSelectedRecords
Les ajouts vont affecter les champs suivants : Alpha, Texte, Numérique, Entier, Entier long, Date, Heure, Booléen, Image, BLOB.
La structure contient les éléments suivants :
typedef
struct
DataRec {
DataType typ;
byte filler;
union
{
TE4D text; /* s_Text32K */
st80 s; /* s_AlphaNumeric */
Real r; /* s_Number */
int2 b; /* s_Bool */
int2 i; /* s_Int16 */
int4 l; /* s_Int32 */
int4 tim; /* s_TimeSec */
Date4D d; /* s_Dates */
Pict4D pic; /* s_Pictures */
Blob4D blob; /* s_Blob */
struct
{
st80 s2 ; int2 unused; }
other ;
}
u;
}
DataRec;
Pour les ajouts d'enregistrements, les principales routines utilisées dans le code sont :
_4D_CreateBuffer(ConnectHandle CIDH,int2 Targetfile)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4DConnection
« Targetfile » : correspond au numéro de fichier sur lequel, on veut créer le Buffer.
_4D_AddToBuffer(ConnectHandle CIDH,BufferHandle Buffer, int2 FieldNumber, DataRec *
Field)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4Dconnection.
« Buffer » : correspond au handle retourné par la routine _4D_CreateBuffer.
« FieldNumber » : correspond au numéro du champ.
« Field » : correspond à la valeur du champ contenu dans le DataRec.
Rechercher un enregistrement▲
Dans l'exemple fourni, la recherche porte sur le champ 4 de la table 1 qui est de type entier, et cherche les enregistrements dont le champ 4 est égal à 999.
La routine à utiliser est :
_4D_Search(ConnectHandle CIDH, SearchRecordPtr What, int4 *
RecordsFound)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4DConnection
« What » : on lui passe un pointeur sur la structure SearchRecord
« RecordsFound » : Elle retourne le nombre d'enregistrements trouvés.
Les structures « SearchLine » et « SerchRecord » :
typedef
struct
SearchLine {
int2 Field_Number;
int2 File_Number;
byte SOP; /* search operator */
byte unused;
DataRec Value;
byte LOP; /* logical operator */
byte unused2,unused3 ;
}
SearchLine;
typedef
struct
SearchRecord {
int2 NB_Lines;
int2 TargetFile;
SearchLine lines[1
];
}
SearchRecord;
typedef
SearchRecord *
SearchRecordPtr;
Dans la source de la routine de recherche, les lignes suivantes se chargent de remplir la structure :
pSearch->
NB_Lines =
1
La recherche concerne le premier niveau de recherche, dans ce cas il existe un seul niveau de recherche
pSearch->
TargetFile =
1
La recherche concerne le fichier numéro 1
pSearch->
lines[0
].Field_Number =
4
La recherche concerne le champ numéro 4 de type Entier
pSearch->
lines[0
].File_Number =
1
Concerne le fichier contenant le champ retenu pour la recherche
pSearch->
lines[0
].SOP =
Equal
L'opérateur de recherche est égal
pSearch->
lines[0
].Value =
data
La valeur à rechercher dans le champ entier est 999
pSearch->
lines[0
].LOP =
None2
L'opérateur logique est vide, car il n'existe qu'une seule ligne de recherche.
Trier les enregistrements▲
Dans l'exemple de cette note technique, le tri s'effectuera sur le champ4 de la table1.
Les structures à remplir pour le tri sont « SortLine » et « SortRecord » :
typedef
struct
SortLine {
int2 Field_Number;
int2 File_Number;
byte Ascent;
}
SortLine;
typedef
struct
SortRecord {
int2 NB_Lines;
int2 TargetFile;
SortLine lines[1
];
}
SortRecord;
typedef
SortRecord *
SortRecordPtr;
La routine à utiliser est :
_4D_Sort(hConnect, pSort)
« hConnect » : correspond au Handle de connexion retourné par la routine
_4D_Open4Dconnection.
« pSort » : correspond au pointeur sur la structure « SortRecord ».
Dans le source de la routine de tri, les lignes suivantes se chargent de remplir la structure :
pSort->
NB_Lines =
1
correspond au numéro du niveau de tri.
pSort->
TargetFile =
1
correspond au numéro du fichier sur lequel porte le tri.
pSort->
lines[0
].File_Number =
1
correspond au numéro de fichier contenant le champ.
pSort->
lines[0
].Field_Number =
4
correspond au champ sur lequel va s'effectuer le tri, il s'agit du champ numéro 4 de type Entier.
pSort->
lines[0
].Ascent =
1
Cette ligne permet de fixer l'ordre de tri, 1 correspond au tri ascendant, 0 correspond au tri descendant.
Manipuler les ensembles▲
Pour l'exemple concernant la manipulation des ensembles, nous aurons besoin de créer deux ensembles : « MySet » et « MySet2 ».
Le 1er ensemble contiendra l'enregistrement courant
Le 2e ensemble contiendra le résultat d'une recherche
On affiche ensuite le nombre d'éléments contenus dans les ensembles « MySet1» et « MySet2 »
Les routines qui concernent les ensembles :
_4D_CreateEmptySet(ConnectHandle CIDH, st80 SetName, int2 Targetfile)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4Dconnection
« SetName» : correspond au nom de l'ensemble vide à créer
« Targetfile » : correspond à l'ID de la table
Cette commande crée un ensemble vide pour la table spécifiée
_4D_CreateSet(ConnectHandle CIDH, st80 SetName, int2 Targetfile)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4Dconnection
« SetName» : nom de l'ensemble à créer.
« Targetfile » : ID de la table
Cette commande crée un nouvel ensemble pour la table spécifiée et met la sélection courante dans l'ensemble spécifié
_4D_AddToSet(ConnectHandle CIDH, st80 SetName, int2 Targetfile)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4Dconnection
« SetName» : correspond au nom de l'ensemble
« TargetName » : correspond à l'identifiant de la table
Cette commande ajoute la sélection courante de la table spécifiée à l'ensemble spécifié
_4D_RecordsInSet(ConnectHandle CIDH, st80 SetName, int4 *
recInSet)
« CIDH »: correspond au Handle de connexion retourné par la routine _4D_Open4DConnection
« SetName» : correspond au nom de l'ensemble
« recInSet » : correspond au nombre d'enregistrements dans l'ensemble
Cette commande retourne dans « recInSet » le nombre d'enregistrements présents dans l'ensemble spécifié.
_4D_ClearSet(ConnectHandle CIDH, st80 SetName)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4DConnection
« SetName » : ensemble à vider
Cette commande libère la mémoire utilisée par l'ensemble.
Manipulation des blobs▲
_4D_SelectAllRecords(ConnectHandle CIDH, int2 Targetfile)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4DConnection
« Targetfile» : correspond au numéro de la table sur laquelle on applique un « tout sélectionner ».
_4D_GotoSelectedRecord(ConnectHandle CIDH, int2 Targetfile, int4 RecNumberInSel)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4DConnection
« Targetfile » : numéro de la table sur laquelle on sélectionne le RecNumberInSel
« RecNumberInSel » : Détermine la position dans la sélection.
_4D_GetFields(ConnectHandle CIDH, ReqFieldRecPtr FieldList, BufferHandle *
Buffer, byte *
IsLocked)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4DConnection
« FieldList » : correspond à la liste des champs concernés « Buffer » : orrespond au Handle sur les données des champs
«IsLocked» : si égal à «1», l'enregistrement est verrouillé.
Pour déterminer le champ à utiliser, il faut remplir la structure suivante :
typedef
struct
ReqFieldRec {
int2 NB_Fields;
int2 TargetFile;
int2 Fields[1
];
}
ReqFieldRec
_4D_GetNthField(ConnectHandle CIDH,BufferHandle Buffer, int2 FieldNumber, DataRec *
Field)
« CIDH » : correspond au Handle de connexion retourné par la routine _4D_Open4DConnection
« Buffer » : handle sur les données du champ retourné par la routine _4D_GetFields
« FieldNumber » : correspond au numéro de champ relatif
« Field » : correspond à la valeur du champ
La structure permettant de récupérer les valeurs des champs est la suivante :
typedef
struct
DataRec {
DataType typ;
byte filler;
union
{
TE4D text; /* s_Text32K */
st80 s; /* s_AlphaNumeric */
Real r; /* s_Number */
int2 b; /* s_Bool */
int2 i; /* s_Int16 */
int4 l; /* s_Int32 */
int4 tim; /* s_TimeSec */
Date4D d; /* s_Dates */
Pict4D pic; /* s_Pictures */
Blob4D blob; /* s_Blob */
struct
{
st80 s2 ; int2 unused; }
other ;
}
u;
}
DataRec;
Si on veut accéder à la taille du champ Blob par exemple, il faut utiliser :
data.u.blob.BlobLen
IV. Mode d'emploi de la Note Technique▲
Cette note technique est fournie avec deux projets :
- Pour la partie Macintosh, nous avons un seul projet qui contient le projet «CFM» et le projet «Mach-O». Le projet a été réalisé sous Metrowerks Code Warrior 9.
- Pour la partie Windows, le projet a été réalisé sous Microsoft Visual Studio.NET
Sous Windows, pour lancer l'exécutable « Open4D », il faut placer le fichier « 4D Open.dll » dans le dossier « Debug ».
La base doit être lancée sur le réseau, le protocole réseau utilisé est TCP :const
short
KNC =
NC_TCPIP dans le code source « C »
Pour faire fonctionner l'exemple, la base doit être ouverte par le 4D Server et doit se composer d'une table contenant des champs de types suivants :
Un champ de type « Alpha », un champ de type « Texte », un champ de type « Numérique », un champ de type « Entier », un champ de type « Entier long », un champ de type « Date », un champ de type « Heure », un champ de type « Booléen », un champ de type « Image », un champ de type « BLOB ».
Pour les formats «Windows» et « CFM »▲
Si vous exécutez le fichier «Open4D» qui se trouve dans le dossier «Debug», vous obtenez la fenêtre « DOS » ci-dessous :
Vous pouvez ensuite rentrer votre choix pour réaliser les différents traitements.
Ajouter et supprimer des enregistrements▲
Supprime tous les enregistrements et ajoute 3 enregistrements pour tous les champs utilisés dans la table de la base de données utilisée par le 4D Server.
Chercher un enregistrement▲
Cherche dans la table numéro 1 et dans le champ numéro 4 de type « entier » la valeur 999.
Trier les enregistrements▲
Le tri est ascendant. Il est réalisé sur le champ numéro 1 de la table 1, le champ est de type « Alphanumérique».
Manipuler des ensembles▲
Permet de créer et de nommer deux ensembles :
- le premier va contenir l'enregistrement courant ;
- le deuxième contient le résultat d'une recherche (recherche dans la table numéro 1 et dans le champ numéro 4 de type «entier » la valeur 999).
Manipuler les Blob▲
Permet de récupérer la nouvelle et l'ancienne taille du champs numéro 10 (qui orrespond au champ Blob) de la table numéro 1.
Pour le format «CFM »▲
Pour le format « Mach-O », la fenêtre ne peut pas être affichée, il faut utiliser le « Terminal » Mac OsX pour afficher les différents traitements réalisés.
Au démarrage de l'exécutable «open4D », les opérations vont être réalisées selon le même ordre que les formats « Windows » et « CFM » : Ajouter et supprimer des enregistrements, chercher un enregistrement, trier un enregistrement, Manipuler des ensembles, manipuler des Blob.
V. Éléments fournis avec la note technique▲
Pour Windows▲
Projet4D 2003
L'exécutable «Open4D » permet d'ouvrir le 4D Server 2003 ainsi que la base de données exemple fournie.
Projet 4D2004
L'exécutable «Open4D» permet d'ouvrir le 4D Server 2004 ainsi que la base de données exemple fournie.
Pour Macintosh▲
L'exécutable généré par le projet « CFM » permet d'ouvrir le 4D Server 2003 ainsi que la base fournie.
L'exécutable généré par le projet « Mach-O » permet d'ouvrir le 4D Server 2004 ainsi que la base fournie.
La base de données exemple 4e Dimension fournie se nomme «OpenLibrairies ».
VI. Conclusion▲
Les utilisateurs des librairies 4D open peuvent, à partir de cette note technique, construire un client « léger » pouvant manipuler les données et des sélections sur le 4D Serveur (Chercher et Trier, Créer des Sélections nommées, Ajouter, Modifier et Supprimer des enregistrements).
Avantage du Client léger▲
La taille du Client léger « 4Dopen » (même avec la librairie 4D Open) est beaucoup plus petite qu'un 4D Client Classique.
Inconvénient du Client léger▲
Il faut programmer toute la partie Interface.
VII. Les Codes source utilisés en Language « C »▲
Code Source Windows▲
#if
__INTEL__
/* #pragma once */
/* #include "ansi_prefix.win32.h" */
/* #include <Windows.h> */
/* Use pre-compiled header instead */
#elif WIN32
/* <-- defined by Visual C++ */
#include
<Windows.h>
#endif
#if WINVER
#undef COLOR_WINDOWFRAME
#undef COLOR_BTNSHADOW
#undef COLOR_BTNFACE
#undef COLOR_BTNHIGHLIGHT
#undef COLOR_BTNTEXT
#undef InsertMenuItem
#undef InsertMenu
#undef AppendMenu
//#include "ASIPORT.H"/*To use Altura headers (in the folder PPC_H, placed in the
project folder)*/
#endif
#define Openlib 1
#include
"Open4D.h"
#include
<stdlib.h>
#include
<string.h>
#include
<stdio.h>
const
short
KNC =
NC_TCPIP;
const
unsigned
char
KStationName[32
]=
"Intel machine
\0
"
;
const
unsigned
char
KUserName[32
]=
"APIUser
\0
"
;
const
unsigned
char
KUserPass[32
]=
"APIPass
\0
"
;
const
unsigned
char
KUserTask[32
]=
"APITask
\0
"
;
const
unsigned
char
kAlphaData[256
] =
"Champs Alpha
\0
"
;
const
unsigned
char
kTexteData[256
] =
"Champs Texte
\0
"
;
unsigned
char
kSetName1[32
] =
"MySet1
\0
"
;
unsigned
char
kSetName2[32
] =
"MySet2
\0
"
;
NetworkComponentHandle hNetworkComponent;
NetworkLocationPtr pNetworkLocation;
ConnectHandle hConnect;
IDRec logRec;
unsigned
char
szName[256
];
int
choix;
void
Menu(void
);
void
initialisation(void
);
int2 StartWSConnection(void
);
void
Check(int2 myErr, char
*
description);
unsigned
char
*
SP2CSTR(unsigned
char
*
pstr);
void
CloseWSConnection(void
);
void
AddRecords(void
);
void
GetBlob(void
);
void
SortRecords(void
);
void
SearchRecords(void
);
void
Sets(void
);
int2 StartWSConnection()
{
int2 myErr;
myErr =
_4D_Select4DServer(szName, &
pNetworkLocation, KNC, hNetworkComponent);
if
(!
myErr)
{
_4D_Open4DConnection(&
logRec, pNetworkLocation, &
hConnect,KNC, hNetworkComponent);
}
return
(myErr);
}
void
CloseWSConnection()
{
_4D_Close4DConnection(hConnect);
}
void
Check(int2 myErr, char
*
description)
{
char
err[256
];
if
(myErr)
{
sprintf(err, "%s: returns %d
\n
"
, description , myErr);
printf(err);
getchar();
}
}
unsigned
char
*
SP2CSTR(unsigned
char
*
pstr)
{
unsigned
char
len =
*
pstr;
memcpy(pstr, pstr+
1
, len);
pstr[len] =
'
\0
'
;
return
pstr;
}
void
initialisation(void
)
{
memcpy(&
logRec.StationName[1
],KStationName, strlen((char
*
)KStationName));
logRec.StationName[0
]=
strlen((char
*
)KStationName);
memcpy(&
logRec.UserName[1
],KUserName, strlen((char
*
)KUserName));
logRec.UserName[0
]=
strlen((char
*
)KUserName);
memcpy(&
logRec.UserPass[1
],KUserPass, strlen((char
*
)KUserPass));
logRec.UserPass[0
]=
strlen((char
*
)KUserPass);
memcpy(&
logRec.TaskName[1
],KUserTask, strlen((char
*
)KUserTask));
logRec.TaskName[0
]=
strlen((char
*
)KUserTask);
}
// Traitement des données
void
AddRecords(void
)
{
BufferHandle hBuffer;
Handle4D hText, hPict, hBlob;
char
*
pText, *
pPict, *
pBlob;
DataRec data;
short
fNb =
1
, nbRec=
1
;
printf("Deleting all records of table : %d
\n
"
, fNb);
Check(_4D_SelectAllRecords(hConnect, fNb),"_4D_SelectAllRecords
\0
"
);
Check(_4D_DeleteSelectedRecords(hConnect, fNb),"_4D_DeleteSelectedRecords
\0
"
);
do
{
printf("Adding records to table : %d et l'enregistrement: %d
\n
"
, fNb, nbRec);
hBuffer =
_4D_CreateBuffer(hConnect, fNb);
data.typ =
s_AlphaNumeric;
memcpy(&
data.u.s[1
], kAlphaData, strlen((char
*
)kAlphaData));
data.u.s[0
] =
strlen((char
*
)kAlphaData);
Check(_4D_AddToBuffer(hConnect, hBuffer, 1
, &
data),"_4D_AddToBuffer
\0
"
);
data.typ =
s_Text32K;
hText =
Alloc4DHandle(strlen((char
*
)kTexteData));
pText =
(char
*
) Lock4DHandle(hText);
memcpy(pText, &
kTexteData, strlen((char
*
)kTexteData));
Unlock4DHandle(hText);
data.u.text.TextLen =
strlen((char
*
)kTexteData);
data.u.text.hText =
hText;
Check(_4D_AddToBuffer(hConnect, hBuffer, 2
, &
data),"_4D_AddToBuffer
\0
"
);
data.typ =
s_Number;
data.u.r.r =
999.999
;
Check(_4D_AddToBuffer(hConnect, hBuffer, 3
, &
data),"_4D_AddToBuffer
\0
"
);
data.typ =
s_Int16;
data.u.i =
999
;
Check(_4D_AddToBuffer(hConnect, hBuffer, 4
, &
data),"_4D_AddToBuffer
\0
"
);
data.typ =
s_Int32;
data.u.l =
999
;
Check(_4D_AddToBuffer(hConnect, hBuffer, 5
, &
data),"_4D_AddToBuffer
\0
"
);
data.typ =
s_Dates;
data.u.d.Day =
27
;
data.u.d.Month =
03
;
data.u.d.Year =
2000
;
Check(_4D_AddToBuffer(hConnect, hBuffer, 6
, &
data),"_4D_AddToBuffer
\0
"
);
data.typ =
s_TimeSec;
data.u.tim =
999
;
Check(_4D_AddToBuffer(hConnect, hBuffer, 7
, &
data),"_4D_AddToBuffer
\0
"
);
data.typ =
s_Bools;
data.u.b =
1
;
Check(_4D_AddToBuffer(hConnect, hBuffer, 8
, &
data),"_4D_AddToBuffer
\0
"
);
hPict =
Alloc4DHandle(strlen((char
*
)kAlphaData));
pPict =
(char
*
) Lock4DHandle(hPict);
memcpy(pPict, &
kAlphaData, strlen((char
*
)kAlphaData));
Unlock4DHandle(hPict);
data.typ =
s_Pictures;
data.u.pic.PictLen =
strlen((char
*
)kAlphaData);
data.u.pic.hPict =
hPict;
Check(_4D_AddToBuffer(hConnect, hBuffer, 9
, &
data),"_4D_AddToBuffer
\0
"
);
hBlob =
Alloc4DHandle(strlen((char
*
)kAlphaData));
pBlob =
(char
*
) Lock4DHandle(hBlob);
memcpy(pBlob, &
kAlphaData, strlen((char
*
)kAlphaData));
Unlock4DHandle(hBlob);
data.typ =
s_Blob;
data.u.blob.BlobLen =
strlen((char
*
)kAlphaData);
data.u.blob.hBlob =
hBlob;
Check(_4D_AddToBuffer(hConnect, hBuffer, 10
, &
data),"_4D_AddToBuffer
\0
"
);
Check(_4D_NewRecord(hConnect, hBuffer),"_4D_NewRecord
\0
"
);
Free4DHandle(hText);
Free4DHandle(hPict);
Free4DHandle(hBlob);
Free4DHandle((Handle4D) hBuffer);
nbRec ++
;
}
while
( nbRec <
4
);
}
void
GetBlob(void
)
{
ReqFieldRecPtr pReq =
(ReqFieldRecPtr) malloc(sizeof
(ReqFieldRec));
BufferHandle hBuf =
0
L;
unsigned
char
IsLocked;
DataRec data;
Check(_4D_SelectAllRecords(hConnect, 1
),"_4D_SelectAllRecords
\0
"
);
Check(_4D_GotoSelectedRecord(hConnect, 1
, 1
),"_4D_GotoSelectedRecord
\0
"
);
pReq->
NB_Fields =
1
;
pReq->
TargetFile =
1
;
pReq->
Fields[0
] =
10
;
Check(_4D_GetFields(hConnect, pReq, &
hBuf, &
IsLocked),"_4D_GetFields
\0
"
);
Check(_4D_GetNthField(hConnect, hBuf, 1
, &
data),"_4D_GetNthField
\0
"
);
printf("Got blob field size : %ld original size was : %d
\n
"
, data.u.blob.BlobLen,
strlen((char
*
) kAlphaData));
Free4DHandle((Handle4D) data.u.blob.hBlob);
Free4DHandle((Handle4D) hBuf);
free(pReq);
}
// Sorts records in ascent order
// if we had more than one field to sort on the server --
// SortRecordPtr pSort = (SortRecordPtr) malloc(sizeof(SortRecord) + ( ( n - 1 ) * sizeof(SortLine) ));
void
SortRecords(void
)
{
SortRecordPtr pSort =
(SortRecordPtr) malloc(sizeof
(SearchRecord));
printf("Sorting records , field #4 in ascent order
\n
"
);
pSort->
NB_Lines =
1
;
pSort->
TargetFile =
1
;
pSort->
lines[0
].File_Number =
1
;
pSort->
lines[0
].Field_Number =
4
;
pSort->
lines[0
].Ascent =
1
;
Check(_4D_Sort(hConnect, pSort),"_4D_Sort
\0
"
);
free(pSort);
}
// Searches records where field #4 of type integer == 999
// if we had more than one field to search on the server --
// SortRecordPtr pSearch = (SearchRecordPtr) malloc(sizeof(SearchRecord) + ( ( n - 1 ) * sizeof(SearchLine) ));
void
SearchRecords(void
)
{
SearchRecordPtr pSearch =
(SearchRecordPtr) malloc(sizeof
(SearchRecord));
DataRec data;
int4 nbRec;
data.typ =
s_Int16;
data.u.i =
999
;
printf("Searching records , field #4 = 999
\n
"
);
pSearch->
NB_Lines =
1
;
pSearch->
TargetFile =
1
;
pSearch->
lines[0
].Field_Number =
4
;
pSearch->
lines[0
].File_Number =
1
;
pSearch->
lines[0
].SOP =
Equal;
pSearch->
lines[0
].Value =
data;
pSearch->
lines[0
].LOP =
None2;
Check(_4D_Search(hConnect, pSearch, &
nbRec),"_4D_Search
\0
"
);
free(pSearch);
printf("found %ld records matching = 999
\n
"
, nbRec);
}
// Demonstrates the use of sets
void
Sets(void
)
{
unsigned
char
pSetName1[32
], pSetName2[32
];
int4 recIn;
memcpy(&
pSetName1[1
], kSetName1, strlen((char
*
)kSetName1));
pSetName1[0
] =
strlen((char
*
)kSetName1);
memcpy(&
pSetName2[1
], kSetName2, strlen((char
*
)kSetName2));
pSetName2[0
] =
strlen((char
*
)kSetName2);
Check(_4D_SelectAllRecords(hConnect, 1
),"_4D_SelectAllRecords
\0
"
);
Check(_4D_CreateEmptySet(hConnect, pSetName1, 1
),"_4D_CreateEmptySet
\0
"
);
Check(_4D_AddToSet(hConnect, pSetName1, 1
),"_4D_AddToSet
\0
"
);
SearchRecords(&
hConnect);
Check(_4D_CreateSet(hConnect, pSetName2, 1
),"_4D_CreateSet
\0
"
);
Check(_4D_RecordsInSet(hConnect, pSetName1, &
recIn),"_4D_RecordsInSet
\0
"
);
printf("Set %s contains : %ld record(s)
\n
"
, SP2CSTR(pSetName1), recIn);
Check(_4D_RecordsInSet(hConnect, pSetName2, &
recIn),"_4D_RecordsInSet
\0
"
);
printf("Set %s contains : %ld record(s)
\n
"
, SP2CSTR(pSetName2), recIn);
Check(_4D_ClearSet(hConnect, pSetName1),"_4D_ClearSet
\0
"
);
Check(_4D_ClearSet(hConnect, pSetName2),"_4D_ClearSet
\0
"
);
}
void
Menu(void
)
{
printf("
\n\n
1 :Ajouter et Supprimer des entregistrements "
);
printf("
\n
2 :Chercher un enregistrement "
);
printf("
\n
3 :Supprimer et Trier les enregistrements "
);
printf("
\n
4 :Manipuler des ensembles"
);
printf("
\n
5 :Manipuler les Blobs"
);
printf("
\n
0 Pour quitter le programme"
);
printf("
\n\n\t
Entrer votre choix : "
);
scanf("%d"
, &
choix);
switch
(choix)
{
case
1
: AddRecords();
break
;
case
2
: SearchRecords();
break
;
case
3
: SortRecords();
break
;
case
4
: Sets();
break
;
case
5
: GetBlob();
break
;
case
0
:
break
;
default
:
printf("
\n\n
Choix Incorrecte ! Appuyer sur une touche !"
);
choix =
getch();
}
}
void
main(void
)
{
initialisation();
_4D_Init4DWS();
hNetworkComponent=
_4D_InitNetworkComponent(KNC);
if
(hNetworkComponent)
{
if
(!
StartWSConnection())
{
do
Menu();
while
(choix !=
0
);
CloseWSConnection();
}
_4D_DeInitNetworkComponent(KNC,hNetworkComponent);
}
_4D_DeInit4DWS();
}
Code Source Macintosh▲
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
#define OpenLib 1
#ifdef __MWERKS__
#ifdef __INTEL__
#define WINVER 0x0400
#define MACVER 0
#endif
#else
#define WINVER 0x0400
#define __INTEL__
#endif
#include
"Open4D.h"
const
short
kNC =
NC_TCPIP;
// change nc here, if u want test with tcp/ip per example
#ifdef __INTEL__
const
unsigned
char
kStationName[32
] =
"Intel machine
\0
"
;
#else
const
unsigned
char
kStationName[32
] =
"Motorola machine
\0
"
;
#endif
const
unsigned
char
kUserName[32
] =
"APIUser
\0
"
;
const
unsigned
char
kUserPass[32
] =
"APIPass
\0
"
;
const
unsigned
char
kUserTask[32
] =
"APITask
\0
"
;
unsigned
char
*
PversCstring(unsigned
char
*
pstr);
void
initialisation();
void
Check(int2 myErr, char
*
description);
int2 StartWSConnection(void
);
void
CloseWSConnection(void
);
void
DisplayServerInfo(void
);
void
DisplayProcessInfo(void
);
void
DisplayStructureInfo(void
);
NetworkComponentHandle hNetworkComponent;
NetworkLocationPtr pNetworkLocation;
ConnectHandle hConnect;
IDRec logRec;
unsigned
char
szName[256
];
// converts a pstring to a cstring
unsigned
char
*
PversCstring(unsigned
char
*
pstr)
{
unsigned
char
len =
*
pstr;
memmove(pstr, pstr+
1
, len);
pstr[len] =
'
\0
'
;
return
pstr;
}
// checks for errors and reports
void
Check(int2 myErr, char
*
description)
{
char
err[256
];
if
( myErr ) {
sprintf(err,"%s : returns %d
\n
"
, description, myErr);
printf(err);
getchar();
}
}
// opens a connection with server and errors if any
int2 StartWSConnection(void
)
{
int2 myErr;
myErr =
_4D_Select4DServer(szName, &
pNetworkLocation, kNC, hNetworkComponent);
if
( !
myErr ) {
myErr =
_4D_Open4DConnection(&
logRec, pNetworkLocation, &
hConnect, kNC,
hNetworkComponent);
}
return
myErr;
}
// closes connection
void
CloseWSConnection(void
)
{
if
(hConnect)
_4D_Close4DConnection (hConnect);
}
void
DisplayServerInfo(void
)
{
ServerInfoRec sInfo;
Date4D d;
int4 l;
unsigned
char
b;
printf("
\n
INFORMATIONS SUR LE 4D SERVEUR
\n
"
);
printf("szName : %s
\n
"
, PversCstring(szName));
Check(_4D_GetServerInfo(hConnect, &
sInfo),"_4D_GetServerInfo
\0
"
);
printf("ServerCurVers : %X
\n
"
, ((sInfo.ServerCurVers &
0xfff
) <<
16
) );
printf("InvertedData : %d
\n
"
, sInfo.ServerHasInvertedData);
Check(_4D_Server_CurrentTime(hConnect, &
l),"_4D_Server_CurrentTime
\0
"
);
printf("Server_CurrentTime : %ld ticks
\n
"
, l);
Check(_4D_Server_CurrentDate(hConnect, &
d),"_4D_Server_CurrentDate
\0
"
);
printf("Server_CurrentDate : %d/%d/%d
\n
"
, d.Day, d.Month, d.Year);
Check(_4D_IsConnectionAsync(hConnect, (unsigned
char
*
) &
b),"_4D_IsConnectionAsync
\0
"
);
printf("IsConnectionAsync ? : %d
\n
"
, b);
printf("
\n
"
);
}
// displays running processes on server
void
DisplayProcessInfo(void
)
{
ListProcessHandle hList =
0
L;
ListProcessPtr pList;
int2 i;
printf("
\n
INFORMATIONS SUR LES PROCESS SERVEUR
\n
"
);
Check(_4D_GetNbUsers(hConnect, &
i),"_4D_GetNbUsers
\0
"
);
printf("GetNbUsers : %d
\n
"
, i);
Check(_4D_GetNbUserProcesses(hConnect, &
i),"_4D_GetNbUserProcesses
\0
"
);
printf("GetNbUserProcesses : %d
\n
"
, i);
Check(_4D_GetListProcess(hConnect, &
hList),"_4D_GetListProcess
\0
"
);
pList =
(ListProcessPtr) Lock4DHandle((Handle4D)hList);
for
( i =
0
; i <
pList->
NB_Process ; i ++
) {
printf("GetListProcess_ProcessInfo[%d]_UserName : %s
\n
"
,
i, PversCstring(pList->
Processes[i].UserName));
printf("GetListProcess_ProcessInfo[%d]_StationName : %s
\n
"
,
i, PversCstring(pList->
Processes[i].StationName));
printf("GetListProcess_ProcessInfo[%d]_Taskname : %s
\n
"
,
i, PversCstring(pList->
Processes[i].Taskname));
printf("GetListProcess_ProcessInfo[%d]_TotalTimeSpent : %ld ticks
\n
"
,
i, pList->
Processes[i].TotalTimeSpent);
printf("GetListProcess_ProcessInfo[%d]_State : %d
\n
"
,
i, pList->
Processes[i].State);
}
Unlock4DHandle((Handle4D)hList);
Free4DHandle((Handle4D)hList);
}
// displays structure
void
DisplayStructureInfo(void
)
{
FileListHandle hList =
0
L;
FileListPtr pList;
FileDefHandle hDef =
0
L;
FileDefPtr pDef;
int2 i, f;
printf("
\n
INFORMATIONS SUR LES TABLES
\n
"
);
Check(_4D_CountFiles(hConnect, &
i),"_4D_CountFiles
\0
"
);
printf("CountFiles : %d
\n
"
, i);
Check(_4D_GetFileList(hConnect, &
hList),"_4D_GetFileList
\0
"
);
pList =
(FileListPtr) Lock4DHandle((Handle4D) hList);
for
( f =
1
; f <=
pList ->
nbFiles ; f ++
) {
Check(_4D_GetFileDefinition(hConnect, f, &
hDef),"_4D_GetFileDefinition
\0
"
);
pDef =
(FileDefPtr) Lock4DHandle((Handle4D)hDef);
printf("GetFileList : %s
\n
"
, PversCstring(pList->
fileNames[f-
1
]));
printf("GetFileDefinition_NB_Fields : %d
\n
"
, pDef->
NB_Fields);
printf("GetFileDefinition_Invisible : %d
\n
"
, pDef->
Invisible);
printf("GetFileDefinition_FileNum : %d
\n
"
, pDef->
FileNum);
printf("GetFileDefinition_Frame : %d/%d/%d/%d
\n
"
, pDef->
Frame.left,
pDef->
Frame.top, pDef->
Frame.right, pDef->
Frame.bottom);
printf("GetFileDefinition_TrigOnSavingNew : %d
\n
"
, pDef->
TrigOnSavingNew);
printf("GetFileDefinition_TrigOnSavingExisting : %d
\n
"
, pDef->
TrigOnSavingExisting);
printf("GetFileDefinition_TrigOnDeleting : %d
\n
"
, pDef->
TrigOnDeleting);
printf("GetFileDefinition_TrigOnLoading : %d
\n
"
, pDef->
TrigOnLoading);
printf("
\n
INFORMATIONS SUR LES CHMAPS
\n
"
);
for
( i =
0
; i <
pDef->
NB_Fields ; i ++
) {
printf("GetFileDefinition_Fields[%d]_Name : %s
\n
"
, i, PversCstring(pDef->
Fields[i].Name));
printf("GetFileDefinition_Fields[%d]_Typ : %d
\n
"
, i, pDef->
Fields[i].Typ);
printf("GetFileDefinition_Fields[%d]_AlphaLen : %d
\n
"
, i, pDef->
Fields[i].AlphaLen);
printf("GetFileDefinition_Fields[%d]_u_SimpleField_RelatedFile : %d
\n
"
,
i, pDef->
Fields[i].u.SimpleField.RelatedFile);
printf("GetFileDefinition_Fields[%d]_u_SimpleField_RelatedField : %d
\n
"
,
i, pDef->
Fields[i].u.SimpleField.RelatedField);
printf("GetFileDefinition_Fields[%d]_u_SimpleField_Att : %X
\n
"
,
i, pDef->
Fields[i].u.SimpleField.Att);
printf("GetFileDefinition_Fields[%d]_u_SimpleField_DiscriminantField : %d
\n
"
,
i, pDef->
Fields[i].u.SimpleField.DiscriminantField);
printf("GetFileDefinition_Fields[%d]_u_PictField_PicAtt : %X
\n
"
,
i, pDef->
Fields[i].u.PictField.PicAtt);
printf("GetFileDefinition_Fields[%d]_u_PictField_CompressDriver : %X
\n
"
,
i, pDef->
Fields[i].u.PictField.CompressDriver);
}
Unlock4DHandle((Handle4D)hDef);
Free4DHandle((Handle4D)hDef);
printf("
\n
"
);
}
Unlock4DHandle((Handle4D)hList);
Free4DHandle((Handle4D)hList);
}
void
initialisation(void
)
{
memcpy(&
logRec.StationName[1
], kStationName, strlen((char
*
)kStationName));
logRec.StationName[0
] =
strlen((char
*
)kStationName);
memcpy(&
logRec.UserName[1
], kUserName, strlen((char
*
)kUserName));
logRec.UserName[0
] =
strlen((char
*
)kUserName);
memcpy(&
logRec.UserPass[1
], kUserPass, strlen((char
*
)kUserPass));
logRec.UserPass[0
] =
strlen((char
*
)kUserPass);
memcpy(&
logRec.TaskName[1
], kUserTask, strlen((char
*
)kUserTask));
logRec.TaskName[0
] =
strlen((char
*
)kUserTask);
}
void
main(void
)
{
printf("GetVersionNumber : %ld
\n
"
, ( _4D_GetVersionNumber() >>
16
));
printf("NB_NetworkComponent : %d
\n
"
, _4D_NB_NetworkComponent());
hNetworkComponent =
_4D_InitNetworkComponent(kNC);
if
( hNetworkComponent ) {
if
( !
StartWSConnection()) {
initialisation();
DisplayServerInfo();
DisplayProcessInfo();
DisplayStructureInfo();
//CloseWSConnection();
}
_4D_DeInitNetworkComponent(kNC, hNetworkComponent);
}
_4D_DeInit4DWS();
}
VIII. Bases exemples▲
Téléchargez les bases exemples :
base exemple Mac
base exemple Windows