Récupération d’informations sur le 4D Server par les librairies 4D Open (Projet Windows, Projet CFM, Projet Mach-0) (2/2)

Aziz ELGHOMARI

- Titre : Récupération d’informations sur le 4D Server par les librairies 4D Open (Projet Windows, Projet CFM, Projet Mach-0) (2/2)

- Auteur : Aziz ELGHOMARI

- Parution : 1 septembre 2004

- Licence : Ce document est issu de https://www.developpez.com et reste la propriété exclusive de son auteur. La copie, modification et/ou distribution par quelque moyen que ce soit est soumise à l'obtention préalable de l'autorisation de l'auteur.

Sommaire

- I. Introduction ♪

- II. Organigramme des opérations qui peuvent être réalisées par les librairies « 4D open »

- Phase 1

- Phase 2

- Phase 3

- Phase 4

- III. Explication des points d'entrées de l'API utilisés dans le code source « C »

- Supprimer et ajouter des enregistrements

- Rechercher un enregistrement

- Trier les enregistrements

- Manipuler les ensembles

- Manipulation des blobs

- IV. Mode d'emploi de la Note Technique

- Pour les formats «Windows» et « CFM »

- Ajouter et supprimer des enregistrements

- Chercher un enregistrement

- Trier les enregistrements

- Manipuler des ensembles

- Manipuler les Blob

- Pour le format «CFM »

- V. Éléments fournis avec la note technique

- Pour Windows

- Pour Macintosh

- VI. Conclusion

- Avantage du Client léger

- Inconvénient du Client léger

- VII. Les Codes source utilisés en Language « C »

- Code Source Windows

- Code Source Macintosh

- VIII. Bases exemples

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.

Résultat de l'opération si on se connecte avec le 4D Client classique

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.

Traitements sur le 4D Server affichés par la console Mac OsX

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 /* &lt;-- 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 = 0L;
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\n1 :Ajouter et Supprimer des entregistrements ");
printf("\n2 :Chercher un enregistrement ");
printf("\n3 :Supprimer et Trier les enregistrements ");
printf("\n4 :Manipuler des ensembles");
printf("\n5 :Manipuler les Blobs");
printf("\n0 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 = 0L;
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 = 0L;
FileListPtr pList;
FileDefHandle hDef = 0L;
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