|
This section includes the following information:
The following example program, which is included on your distribution media, shows how to perform several of the more common Btrieve operations, and it performs those operations in the order required by the MicroKernel's dependencies (for example, you must open a file before performing I/O to it).
For an example of the Btrieve Login operation, see C++ Program Example of Btrieve Login .
/********************************************************** ** Copyright 2003 Pervasive Software Inc. All Rights Reserved ** ************************************************************/ /*********************************************************** BTRSAMP.C This is a simple sample designed to allow you to confirm your ability to compile, link, and execute a Btrieve application for your target environment using your compiler tools. This program demonstrates the C/C++ interface for Btrieve for MS Windows, NetWare NLM, MS Windows NT/2000 and Windows 9X. This program does the following operations on the sample database: - gets the Microkernel Database Engine version - opens sample.btr - gets a record on a known value of Key 0 - displays the retrieved record - performs a stat operation - creates an empty `clone' of sample.btr and opens it - performs a `Get Next Extended' operation to extract a subset of the records in sample.btr - inserts those records into the cloned file - closes both files IMPORTANT: You must specify the complete path to the directory that contains the sample Btrieve data file, `sample.btr'. See IMPORTANT, below. You can compile and run this program on any of the platforms supported by the interface modules. Platforms are indicated by the platform switches listed in `btrapi.h'. For MS Windows you should make an application that allows standard output via printf(). Note that most C/C++ compilers support standard I/O Windows applications. For MS Windows NT, you should make a console application. See the prologue in `btrapi.h' for information on how to select a target platform for your application. You must specify a target platform. ***********************************************************/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <btrapi.h> #include <btrconst.h> /*********************************************************** Constants ************************************************************/ /*********************************************************** IMPORTANT: You should modify the following to specify the complete path to `sample.btr' for your environment. ***********************************************************/ #ifdef BTI_NLM #define FILE1_NAME "sys:\\pvsw\\samples\\sample.btr" #else #define FILE1_NAME "c:\\pvsw\\samples\\sample.btr" #endif #ifdef BTI_NLM #define FILE2_NAME "sys:\\pvsw\\samples\\sample2.btr" #else #define FILE2_NAME "c:\\pvsw\\samples\\sample2.btr" #endif #define EXIT_WITH_ERROR 1 #define TRUE 1 #define FALSE 0 #define VERSION_OFFSET 0 #define REVISION_OFFSET 2 #define PLATFORM_ID_OFFSET 4 #define MY_THREAD_ID 50 /* Don't pad our structures */ #if defined(__BORLANDC__) #pragma option -a- #else #if defined(_MSC_VER) || defined(__WATCOMC__) #pragma pack(1) #endif #endif /*********************************************************** Type definitions for Client ID and version Structures ************************************************************/ typedef struct { BTI_CHAR networkAndNode[12]; BTI_CHAR applicationID[2]; BTI_WORD threadID; } CLIENT_ID; typedef struct { BTI_SINT Version; BTI_SINT Revision; BTI_CHAR MKDEId; } VERSION_STRUCT; /*********************************************************** Definition of record from `sample.btr' ************************************************************/ typedef struct { BTI_LONG ID; BTI_CHAR FirstName[16]; BTI_CHAR LastName[26]; BTI_CHAR Street[31]; BTI_CHAR City[31]; BTI_CHAR State[3]; BTI_CHAR Zip[11]; BTI_CHAR Country[21]; BTI_CHAR Phone[14]; } PERSON_STRUCT; /*********************************************************** Type definitions for Stat/Create structure ************************************************************/ typedef struct { BTI_SINT recLength; BTI_SINT pageSize; BTI_SINT indexCount; BTI_CHAR reserved[4]; BTI_SINT flags; BTI_BYTE dupPointers; BTI_BYTE notUsed; BTI_SINT allocations; } FILE_SPECS; typedef struct { BTI_SINT position; BTI_SINT length; BTI_SINT flags; BTI_CHAR reserved[4]; BTI_CHAR type; BTI_CHAR null; BTI_CHAR notUsed[2]; BTI_BYTE manualKeyNumber; BTI_BYTE acsNumber; } KEY_SPECS; typedef struct { FILE_SPECS fileSpecs; KEY_SPECS keySpecs[5]; } FILE_CREATE_BUF; /*********************************************************** Structure type definitions for Get Next Extended operation ************************************************************/ typedef struct { BTI_SINT descriptionLen; BTI_CHAR currencyConst[2]; BTI_SINT rejectCount; BTI_SINT numberTerms; } GNE_HEADER; typedef struct { BTI_CHAR fieldType; BTI_SINT fieldLen; BTI_SINT fieldOffset; BTI_CHAR comparisonCode; BTI_CHAR connector; BTI_CHAR value[3]; } TERM_HEADER; typedef struct { BTI_SINT maxRecsToRetrieve; BTI_SINT noFieldsToRetrieve; } RETRIEVAL_HEADER; typedef struct { BTI_SINT fieldLen; BTI_SINT fieldOffset; } FIELD_RETRIEVAL_HEADER; typedef struct { GNE_HEADER gneHeader; TERM_HEADER term1; TERM_HEADER term2; RETRIEVAL_HEADER retrieval; FIELD_RETRIEVAL_HEADER recordRet; } PRE_GNE_BUFFER; typedef struct { BTI_SINT recLen; BTI_LONG recPos; PERSON_STRUCT personRecord; } RETURNED_REC; typedef struct { BTI_SINT numReturned; RETURNED_REC recs[20]; } POST_GNE_BUFFER; typedef union { PRE_GNE_BUFFER preBuf; POST_GNE_BUFFER postBuf; } GNE_BUFFER, BTI_FAR* GNE_BUFFER_PTR; /* restore structure packing */ #if defined(__BORLANDC__) #pragma option -a. #else #if defined(_MSC_VER) || defined(__WATCOMC__) #pragma pack() #endif #endif /*********************************************************** Main ***********************************************************/ int main(void) { /* Btrieve function parameters */ BTI_BYTE posBlock1[128]; BTI_BYTE posBlock2[128]; BTI_BYTE dataBuf[255]; BTI_WORD dataLen; BTI_BYTE keyBuf1[255]; BTI_BYTE keyBuf2[255]; BTI_WORD keyNum = 0; BTI_BYTE btrieveLoaded = FALSE; BTI_LONG personID; BTI_BYTE file1Open = FALSE; BTI_BYTE file2Open = FALSE; BTI_SINT status; BTI_SINT getStatus = -1; BTI_SINT i; BTI_SINT posCtr; CLIENT_ID clientID; VERSION_STRUCT versionBuffer[3]; FILE_CREATE_BUF fileCreateBuf; GNE_BUFFER_PTR gneBuffer; PERSON_STRUCT personRecord; printf("**************** Btrieve C/C++ Interface Demo ****************\n\n"); /* set up the Client ID */ memset(clientID.networkAndNode, 0, sizeof(clientID.networkAndNode)); memcpy(clientID.applicationID, "MT", 2); /* must be greater than "AA" */ clientID.threadID = MY_THREAD_ID; memset(versionBuffer, 0, sizeof(versionBuffer)); dataLen = sizeof(versionBuffer); status = BTRVID( B_VERSION, posBlock1, &versionBuffer, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); if (status == B_NO_ERROR) { printf("Btrieve Versions returned are: \n"); for (i = 0; i < 3; i++) { if (versionBuffer[i].Version != 0) { printf(" %d.%d %c\n", versionBuffer[i].Version, versionBuffer[i].Revision, versionBuffer[i].MKDEId); } } printf("\n"); btrieveLoaded = TRUE; } else { printf("Btrieve B_VERSION status = %d\n", status); if (status != B_RECORD_MANAGER_INACTIVE) { btrieveLoaded = TRUE; } } /* clear buffers */ if (status == B_NO_ERROR) { memset(dataBuf, 0, sizeof(dataBuf)); memset(keyBuf1, 0, sizeof(keyBuf1)); memset(keyBuf2, 0, sizeof(keyBuf2)); } /* open sample.btr */ if (status == B_NO_ERROR) { strcpy((BTI_CHAR *)keyBuf1, FILE1_NAME); strcpy((BTI_CHAR *)keyBuf2, FILE2_NAME); keyNum = 0; dataLen = 0; status = BTRVID( B_OPEN, posBlock1, dataBuf, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_OPEN status (sample.btr) = %d\n", status); if (status == B_NO_ERROR) { file1Open = TRUE; } } /* get the record with key 0 = 263512477 using B_GET_EQUAL */ if (status == B_NO_ERROR) { memset(&personRecord, 0, sizeof(personRecord)); dataLen = sizeof(personRecord); personID = 263512477; /* this is really a social security number */ *(BTI_LONG BTI_FAR *)&keyBuf1[0] = personID; keyNum = 0; status = BTRVID( B_GET_EQUAL, posBlock1, &personRecord, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_GET_EQUAL status = %d\n", status); if (status == B_NO_ERROR) { printf("\n"); printf("The retrieved record is:\n"); printf("ID: %ld\n", personRecord.ID); printf("Name: %s %s\n", personRecord.FirstName, personRecord.LastName); printf("Street: %s\n", personRecord.Street); printf("City: %s\n", personRecord.City); printf("State: %s\n", personRecord.State); printf("Zip: %s\n", personRecord.Zip); printf("Country: %s\n", personRecord.Country); printf("Phone: %s\n", personRecord.Phone); printf("\n"); } } /* perform a stat operation to populate the create buffer */ memset(&fileCreateBuf, 0, sizeof(fileCreateBuf)); dataLen = sizeof(fileCreateBuf); keyNum = (BTI_WORD)-1; status = BTRVID(B_STAT, posBlock1, &fileCreateBuf, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); if (status == B_NO_ERROR) { /* create and open sample2.btr */ keyNum = 0; dataLen = sizeof(fileCreateBuf); status = BTRVID(B_CREATE, posBlock2, &fileCreateBuf, &dataLen, keyBuf2, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_CREATE status = %d\n", status); } if (status == B_NO_ERROR) { keyNum = 0; dataLen = 0; status = BTRVID( B_OPEN, posBlock2, dataBuf, &dataLen, keyBuf2, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_OPEN status (sample2.btr) = %d\n", status); if (status == B_NO_ERROR) { file2Open = TRUE; } } /* now extract data from the original file, insert into new one */ if (status == B_NO_ERROR) { /* getFirst to establish currency */ keyNum = 2; /* STATE-CITY index */ memset(&personRecord, 0, sizeof(personRecord)); memset(&keyBuf2[0], 0, sizeof(keyBuf2)); dataLen = sizeof(personRecord); getStatus = BTRVID( B_GET_FIRST, posBlock1, &personRecord, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_GET_FIRST status (sample.btr) = %d\n\n", getStatus); } gneBuffer = malloc(sizeof(GNE_BUFFER)); if (gneBuffer == NULL) { printf("Insufficient memory to allocate buffer"); return(EXIT_WITH_ERROR); } memset(gneBuffer, 0, sizeof(GNE_BUFFER)); memcpy(&gneBuffer->preBuf.gneHeader.currencyConst[0], "UC", 2); while (getStatus == B_NO_ERROR) { gneBuffer->preBuf.gneHeader.rejectCount = 0; gneBuffer->preBuf.gneHeader.numberTerms = 2; posCtr = sizeof(GNE_HEADER); /* fill in the first condition */ gneBuffer->preBuf.term1.fieldType = 11; gneBuffer->preBuf.term1.fieldLen = 3; gneBuffer->preBuf.term1.fieldOffset = 108; gneBuffer->preBuf.term1.comparisonCode = 1; gneBuffer->preBuf.term1.connector = 2; memcpy(&gneBuffer->preBuf.term1.value[0], "TX", 2); posCtr += sizeof(TERM_HEADER); /* fill in the second condition */ gneBuffer->preBuf.term2.fieldType = 11; gneBuffer->preBuf.term2.fieldLen = 3; gneBuffer->preBuf.term2.fieldOffset = 108; gneBuffer->preBuf.term2.comparisonCode = 1; gneBuffer->preBuf.term2.connector = 0; memcpy(&gneBuffer->preBuf.term2.value[0], "CA", 2); posCtr += sizeof(TERM_HEADER); /* fill in the projection header to retrieve whole record */ gneBuffer->preBuf.retrieval.maxRecsToRetrieve = 20; gneBuffer->preBuf.retrieval.noFieldsToRetrieve = 1; posCtr += sizeof(RETRIEVAL_HEADER); gneBuffer->preBuf.recordRet.fieldLen = sizeof(PERSON_STRUCT); gneBuffer->preBuf.recordRet.fieldOffset = 0; posCtr += sizeof(FIELD_RETRIEVAL_HEADER); gneBuffer->preBuf.gneHeader.descriptionLen = posCtr; dataLen = sizeof(GNE_BUFFER); getStatus = BTRVID( B_GET_NEXT_EXTENDED, posBlock1, gneBuffer, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_GET_NEXT_EXTENDED status = %d\n", getStatus); /* Get Next Extended can reach end of file and still return some records */ if ((getStatus == B_NO_ERROR) || (getStatus == B_END_OF_FILE)) { printf("GetNextExtended returned %d records.\n", gneBuffer- >postBuf.numReturned); for (i = 0; i < gneBuffer->postBuf.numReturned; i++) { dataLen = sizeof(PERSON_STRUCT); memcpy(dataBuf, &gneBuffer->postBuf.recs[i].personRecord, dataLen); status = BTRVID( B_INSERT, posBlock2, dataBuf, &dataLen, keyBuf2, -1, /* no currency change */ (BTI_BUFFER_PTR)&clientID); } printf("Inserted %d records in new file, status = %d\n\n", gneBuffer->postBuf.numReturned, status); } memset(gneBuffer, 0, sizeof(GNE_BUFFER)); memcpy(&gneBuffer->preBuf.gneHeader.currencyConst[0], "EG", 2); } free(gneBuffer); gneBuffer = NULL; /* close open files */ if (file1Open) { dataLen = 0; status = BTRVID( B_CLOSE, posBlock1, dataBuf, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_CLOSE status (sample.btr) = %d\n", status); } if (file2Open) { dataLen = 0; status = BTRVID( B_CLOSE, posBlock2, dataBuf, &dataLen, keyBuf2, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_CLOSE status (sample2.btr) = %d\n", status); } return(status); }
The following example program, which is included on your distribution media as loginapi.c, shows how to perform the Btrieve login operation in the context of other operations, and it performs those operations in the order required by the MicroKernel's dependencies (for example, you must open a file before performing I/O to it).
For an example of other Btrieve operations, see C++ Program Example .
/********************************************************************* ** ** Copyright 1982-2003 Pervasive Software Inc. All Rights Reserved ** *********************************************************************/ /********************************************************************* LOGINAPI.C This is a simple sample designed to allow you to confirm your ability to compile, link, and execute a Btrieve application for your target environment using your compiler tools. This program demonstrates how to use new Btrieve login API with secured database. Login API available with Pervasive.SQL 8.50. To run a program DefaultDb database should be secured and security mode set to database authentication and authorization. Use PCC to set that up. This program does the following operations on the DefaultDb database: - Logs in to DefaultDb database using Btrieve operation B_LOGIN (78) - opens sample.btr - gets a record on a known value of Key 0 - displays the retrieved record - closes sample.btr - logs out from DefaultDB database Second part demonstrates how to use URI in Btrieve Open call. - opens sample.btr using URI string in a key buffer. - gets a record on a known value of Key 0 - displays the retrieved record - closes sample.btr IMPORTANT: You must specify the complete path to the directory that contains the sample Btrieve data file, 'sample.btr'. See IMPORTANT, below. You can compile and run this program on any of the platforms supported by the interface modules. Platforms are indicated by the platform switches listed in 'btrapi.h'. For MS Windows you should make an application that allows standard output via printf(). Note that most C/C++ compilers support standard I/O Windows applications. For MS Windows NT or OS2, you should make a console application. See the prologue in 'btrapi.h' for information on how to select a target platform for your application. You must specify a target platform. *********************************************************************/ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <btrapi.h> #include <btrconst.h> /********************************************************************* Constants *********************************************************************/ /******************************************************************** IMPORTANT: You should modify the following to specify the complete path to 'sample.btr' for your environment. ********************************************************************/ #ifdef BTI_LINUX #define FILE_NAME "/usr/local/psql/data/samples/sample.btr" #else #ifdef BTI_NLM #define FILE_NAME "sys:\\pvsw\\samples\\sample.btr" #else #define FILE_NAME "c:\\pvsw\\samples\\sample.btr" #endif #endif #define EXIT_WITH_ERROR 1 #define TRUE 1 #define FALSE 0 #define MY_THREAD_ID 50 /* Don't pad our structures */ #if defined(__BORLANDC__) #pragma option -a- #else #if defined(_MSC_VER) || defined(__WATCOMC__) #pragma pack(1) #endif #endif /********************************************************************* Type definitions for Client ID and version Structures *********************************************************************/ typedef struct { BTI_CHAR networkAndNode[12]; BTI_CHAR applicationID[2]; BTI_WORD threadID; } CLIENT_ID; typedef struct { BTI_SINT Version; BTI_SINT Revision; BTI_CHAR MKDEId; } VERSION_STRUCT; /********************************************************************* Definition of record from 'sample.btr' *********************************************************************/ typedef struct { BTI_LONG ID; BTI_CHAR FirstName[16]; BTI_CHAR LastName[26]; BTI_CHAR Street[31]; BTI_CHAR City[31]; BTI_CHAR State[3]; BTI_CHAR Zip[11]; BTI_CHAR Country[21]; BTI_CHAR Phone[14]; } PERSON_STRUCT; /* restore structure packing */ #if defined(__BORLANDC__) #pragma option -a. #else #if defined(_MSC_VER) || defined(__WATCOMC__) #pragma pack() #endif #endif /********************************************************************* Main *********************************************************************/ int main(void) { /* Btrieve function parameters */ BTI_BYTE posBlock[128]; BTI_BYTE dataBuf[255]; BTI_WORD dataLen; BTI_BYTE keyBuf[255]; BTI_WORD keyNum = 0; BTI_LONG personID; BTI_BYTE fileOpen = FALSE; BTI_SINT status = 0; CLIENT_ID clientID; PERSON_STRUCT personRecord; /* define URI string to open sample.btr file in DefaultDb database*/ /* SQL security is set for DefaultDb with User name "Master" and passord "master" */ BTI_CHAR *URI_STRING1 = "btrv://Master@localhost/ defaultdb?pwd=master"; BTI_CHAR *URI_STRING2 = "btrv://Master@localhost/defaultdb?file=/usr/ local/psql/data/samples/sample.btr&pwd=master"; printf("****** Btrieve C/C++ Interface Demo for Login API *****\n\n"); /* set up the Client ID */ memset(clientID.networkAndNode, 0, sizeof(clientID.networkAndNode)); memcpy(clientID.applicationID, "MT", 2); /* must be > than "AA" */ clientID.threadID = MY_THREAD_ID; /* Login to secure database */ memset(dataBuf, 0, sizeof(dataBuf)); strcpy(keyBuf, URI_STRING1); keyNum = 0; status = BTRVID( B_LOGIN, posBlock, dataBuf, &dataLen, keyBuf, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_LOGIN status = %d\n", status); /* clear buffers */ memset(dataBuf, 0, sizeof(dataBuf)); memset(keyBuf , 0, sizeof(keyBuf)); /* open sample.btr */ strcpy((BTI_CHAR *)keyBuf, FILE_NAME); keyNum = 0; dataLen = 0; status = BTRVID( B_OPEN, posBlock, dataBuf, &dataLen, keyBuf, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_OPEN status (sample.btr) = %d\n", status); if (status == B_NO_ERROR) { fileOpen = TRUE; } /* get the record with key 0 = 263512477 using B_GET_EQUAL */ if (status == B_NO_ERROR) { memset(&personRecord, 0, sizeof(personRecord)); dataLen = sizeof(personRecord); personID = 263512477; /* this is really a social security number */ *(BTI_LONG BTI_FAR *)&keyBuf[0] = personID; keyNum = 0; status = BTRVID( B_GET_EQUAL, posBlock, &personRecord, &dataLen, keyBuf, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_GET_EQUAL status = %d\n", status); if (status == B_NO_ERROR) { printf("\n"); printf("The retrieved record is:\n"); printf("ID: %ld\n", personRecord.ID); printf("Name: %s %s\n", personRecord.FirstName, personRecord.LastName); printf("Street: %s\n", personRecord.Street); printf("City: %s\n", personRecord.City); printf("State: %s\n", personRecord.State); printf("Zip: %s\n", personRecord.Zip); printf("Country: %s\n", personRecord.Country); printf("Phone: %s\n", personRecord.Phone); printf("\n"); } } /* close open files */ if (fileOpen) { dataLen = 0; status = BTRVID( B_CLOSE, posBlock, dataBuf, &dataLen, keyBuf, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_CLOSE status (sample.btr) = %d\n", status); } /* Logout from secure database */ memset(dataBuf, 0, sizeof(dataBuf)); strcpy(keyBuf, URI_STRING1); keyNum = 1; status = BTRVID( B_LOGIN, posBlock, dataBuf, &dataLen, keyBuf, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve logout status = %d\n", status); printf("\n\n"); /* Following example uses URI string in Btrieve Open call */ printf("*** This example uses URI string in Btrieve Open call ***\n\n"); /* set up the Client ID */ memset(clientID.networkAndNode, 0, sizeof(clientID.networkAndNode)); memcpy(clientID.applicationID, "MT", 2); /* must be > than "AA" */ clientID.threadID = MY_THREAD_ID; /* clear buffers */ memset(dataBuf, 0, sizeof(dataBuf)); memset(keyBuf , 0, sizeof(keyBuf)); /* open sample.btr */ strcpy((BTI_CHAR *)keyBuf, URI_STRING2); keyNum = 0; dataLen = 0; status = BTRVID( B_OPEN, posBlock, dataBuf, &dataLen, keyBuf, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_OPEN status (sample.btr) = %d\n", status); if (status == B_NO_ERROR) { fileOpen = TRUE; } /* get the record with key 0 = 263512477 using B_GET_EQUAL */ if (status == B_NO_ERROR) { memset(&personRecord, 0, sizeof(personRecord)); dataLen = sizeof(personRecord); personID = 263512477; /* this is really a social security number */ *(BTI_LONG BTI_FAR *)&keyBuf[0] = personID; keyNum = 0; status = BTRVID( B_GET_EQUAL, posBlock, &personRecord, &dataLen, keyBuf, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_GET_EQUAL status = %d\n", status); if (status == B_NO_ERROR) { printf("\n"); printf("The retrieved record is:\n"); printf("ID: %ld\n", personRecord.ID); printf("Name: %s %s\n", personRecord.FirstName, personRecord.LastName); printf("Street: %s\n", personRecord.Street); printf("City: %s\n", personRecord.City); printf("State: %s\n", personRecord.State); printf("Zip: %s\n", personRecord.Zip); printf("Country: %s\n", personRecord.Country); printf("Phone: %s\n", personRecord.Phone); printf("\n"); } } /* close open files */ if (fileOpen) { dataLen = 0; status = BTRVID( B_CLOSE, posBlock, dataBuf, &dataLen, keyBuf, keyNum, (BTI_BUFFER_PTR)&clientID); printf("Btrieve B_CLOSE status (sample.btr) = %d\n", status); } return(status); }
The C Interface for Btrieve is platform-independent and compiler-independent. In general for your compiler, you must do the following:
This section provides instructions for some common development environments. If your development environment is not discussed, you can adapt these instructions.
In Microsoft Visual C++, to compile, link, and run the program example:
Microsoft Visual C++ builds the program example and places BtrSamp.exe in your project file directory.
In Watcom C++, to compile, link, and run the program example:
WATCOM C++ builds the program example and places BtrSamp.exe in your project file directory.
In Borland C++, to compile, link, and run the program example:
Borland C++ builds the program example and places BtrSamp.exe in your project file directory.
In C++ Builder, to compile, link, and run the program example:
C++ Builder builds the program example and places CBBtrv.exe in your project file directory.
The following example C++ Builder program shows how to perform several of the more common Btrieve operations, and it performs those operations in the order required by the MicroKernel's dependencies (for example, you must open a file before performing I/O to it).
/********************************************************** ** ** Copyright 2003 Pervasive Software Inc. ** All Rights Reserved ***********************************************************/ /*********************************************************** CBBMain.cpp This is a simple sample designed to allow you to confirm your ability to compile, link, and execute a Btrieve application for your target environment using your compiler tools. This program demonstrates the C/C++ interface for Btrieve for MS Windows NT and Windows 9X/ME with Borland's C++ Builder. This program does the following operations on the sample database: - gets the Microkernel Database Engine version - opens sample.btr - gets a record on a known value of Key 0 - displays the retrieved record - performs a stat operation - creates an empty `clone' of sample.btr and opens it - performs a `Get Next Extended' operation to extract a subset `of the records in sample.btr - inserts those records into the cloned file - closes both files To compile this sample, you must make the following files from the Btrieve "C" interface directory available to the IDE: - btrapi.c - btrapi.h - btrconst.h IMPORTANT: You must specify the complete path to the directory that contains the sample Btrieve data file, `sample.btr'. See IMPORTANT, below. ***********************************************************/ //---------------------------------------------------------- #include <vcl\vcl.h> #pragma hdrstop #include "CBBMain.h" #include <btrapi.h> #include <btrconst.h> //---------------------------------------------------------- #pragma resource "*.dfm" /*********************************************************** Constants ***********************************************************/ #define EXIT_WITH_ERROR 1 #define TRUE 1 #define FALSE 0 #define VERSION_OFFSET 0 #define REVISION_OFFSET 2 #define PLATFORM_ID_OFFSET 4 #define MY_THREAD_ID 50 /* Don't pad our structures */ /* Borland's help says this is the default. Don't believe it.*/ #pragma option -a1 /*********************************************************** Type definitions for Client ID and version Structures ***********************************************************/ typedef struct { BTI_CHAR networkAndNode[12]; BTI_CHAR applicationID[2]; BTI_WORD threadID; } CLIENT_ID; typedef struct { BTI_SINT Version; BTI_SINT Revision; BTI_CHAR MKDEId; } VERSION_STRUCT; /*********************************************************** Definition of record from `sample.btr' ***********************************************************/ typedef struct { BTI_LONG ID; BTI_CHAR FirstName[16]; BTI_CHAR LastName[26]; BTI_CHAR Street[31]; BTI_CHAR City[31]; BTI_CHAR State[3]; BTI_CHAR Zip[11]; BTI_CHAR Country[21]; BTI_CHAR Phone[14]; } PERSON_STRUCT; /*********************************************************** Type definitions for Stat/Create structure ***********************************************************/ typedef struct { BTI_SINT recLength; BTI_SINT pageSize; BTI_SINT indexCount; BTI_CHAR reserved[4]; BTI_SINT flags; BTI_BYTE dupPointers; BTI_BYTE notUsed; BTI_SINT allocations; } FILE_SPECS; typedef struct { BTI_SINT position; BTI_SINT length; BTI_SINT flags; BTI_CHAR reserved[4]; BTI_CHAR type; BTI_CHAR null; BTI_CHAR notUsed[2]; BTI_BYTE manualKeyNumber; BTI_BYTE acsNumber; } KEY_SPECS; typedef struct { FILE_SPECS fileSpecs; KEY_SPECS keySpecs[5]; } FILE_CREATE_BUF; /*********************************************************** Structure type definitions for Get Next Extended operation ***********************************************************/ typedef struct { BTI_SINT descriptionLen; BTI_CHAR currencyConst[2]; BTI_SINT rejectCount; BTI_SINT numberTerms; } GNE_HEADER; typedef struct { BTI_CHAR fieldType; BTI_SINT fieldLen; BTI_SINT fieldOffset; BTI_CHAR comparisonCode; BTI_CHAR connector; BTI_CHAR value[3]; } TERM_HEADER; typedef struct { BTI_SINT maxRecsToRetrieve; BTI_SINT noFieldsToRetrieve; } RETRIEVAL_HEADER; typedef struct { BTI_SINT fieldLen; BTI_SINT fieldOffset; } FIELD_RETRIEVAL_HEADER; typedef struct { GNE_HEADER gneHeader; TERM_HEADER term1; TERM_HEADER term2; RETRIEVAL_HEADER retrieval; FIELD_RETRIEVAL_HEADER recordRet; } PRE_GNE_BUFFER; typedef struct { BTI_SINT recLen; BTI_LONG recPos; PERSON_STRUCT personRecord; } RETURNED_REC; typedef struct { BTI_SINT numReturned; RETURNED_REC recs[20]; } POST_GNE_BUFFER; typedef union { PRE_GNE_BUFFER preBuf; POST_GNE_BUFFER postBuf; } GNE_BUFFER, BTI_FAR* GNE_BUFFER_PTR; //---------------------------------------------------------- // non-exported forward declarations void printLB(TListBox *LB, char *msg); TForm1 *Form1; //---------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //---------------------------------------------------------- void __fastcall TForm1::ExitButtonClick(TObject *Sender) { Form1->Close(); } //---------------------------------------------------------- void __fastcall TForm1::RunButtonClick(TObject *Sender) { runTest(); } /*********************************************************** Helper function to write to ListBox ***********************************************************/ void printLB(TListBox *LB, char *msg) { LB->Items->Add(msg); } /*********************************************************** This is where all the work gets done ***********************************************************/ BTI_SINT runTest(void) { /* Btrieve function parameters */ BTI_BYTE posBlock1[128]; BTI_BYTE posBlock2[128]; BTI_BYTE dataBuf[255]; BTI_WORD dataLen; BTI_BYTE keyBuf1[255]; BTI_BYTE keyBuf2[255]; BTI_WORD keyNum = 0; BTI_BYTE btrieveLoaded = FALSE; BTI_LONG personID; BTI_BYTE file1Open = FALSE; BTI_BYTE file2Open = FALSE; BTI_SINT status; BTI_SINT getStatus; BTI_SINT i; BTI_SINT posCtr; CLIENT_ID clientID; VERSION_STRUCT versionBuffer[3]; FILE_CREATE_BUF fileCreateBuf; GNE_BUFFER_PTR gneBuffer; PERSON_STRUCT personRecord; BTI_CHAR tmpBuf[1024]; /********************************************************** Print the program title **********************************************************/ printLB(Form1->ListBox1, "**** Btrieve -- C++ Builder Sample ****" ); /* set up the Client ID */ memset(clientID.networkAndNode, 0, sizeof(clientID.networkAndNode)); memcpy(clientID.applicationID, "MT", 2); /* must be greater than "AA" */ clientID.threadID = MY_THREAD_ID; memset(versionBuffer, 0, sizeof(versionBuffer)); dataLen = sizeof(versionBuffer); status = BTRVID( B_VERSION, posBlock1, &versionBuffer, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); if (status == B_NO_ERROR) { strcpy(tmpBuf, "Btrieve Versions returned are: " ); printLB(Form1->ListBox1, tmpBuf); for (i = 0; i < 3; i++) { if (versionBuffer[i].Version != 0) { sprintf(tmpBuf, " %d.%d %c", versionBuffer[i].Version, versionBuffer[i].Revision, versionBuffer[i].MKDEId ); printLB(Form1->ListBox1, tmpBuf); } } printLB(Form1->ListBox1, ""); btrieveLoaded = TRUE; } else { sprintf(tmpBuf, "Btrieve B_VERSION status = %d", status ); printLB(Form1->ListBox1, tmpBuf); if ( status != B_RECORD_MANAGER_INACTIVE ) { btrieveLoaded = TRUE; } } /* clear buffers */ if (status == B_NO_ERROR) { memset(dataBuf, 0, sizeof(dataBuf)); memset(keyBuf1, 0, sizeof(keyBuf1)); memset(keyBuf2, 0, sizeof(keyBuf2)); } /* open sample.btr */ if (status == B_NO_ERROR) { /******************************************************** IMPORTANT: You should modify the following to specify the complete path to `sample.btr' for your environment. ********************************************************/ strcpy((BTI_CHAR *)keyBuf1, "c:\\sample\\sample.btr"); strcpy((BTI_CHAR *)keyBuf2, "c:\\sample\\sample2.btr"); keyNum = 0; dataLen = 0; status = BTRVID( B_OPEN, posBlock1, dataBuf, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); sprintf(tmpBuf, "Btrieve B_OPEN status = %d", status ); printLB(Form1->ListBox1, tmpBuf); if (status == B_NO_ERROR) { file1Open = TRUE; } } /* get the record with key 0 = 263512477 using B_GET_EQUAL */ if (status == B_NO_ERROR) { memset(&personRecord, 0, sizeof(personRecord)); dataLen = sizeof(personRecord); personID = 263512477; /* this is really a social security number */ *(BTI_LONG BTI_FAR *)&keyBuf1[0] = personID; keyNum = 0; status = BTRVID( B_GET_EQUAL, posBlock1, &personRecord, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); sprintf(tmpBuf, "Btrieve B_GET_EQUAL status = %d", status ); printLB(Form1->ListBox1, tmpBuf); if (status == B_NO_ERROR) { sprintf(tmpBuf, "" ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "The retrieved record is:" ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "ID: %ld", personRecord.ID ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "Name: %s %s", personRecord.FirstName, personRecord.LastName ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "Street: %s", personRecord.Street ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "City: %s", personRecord.City ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "State: %s", personRecord.State ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "Zip: %s", personRecord.Zip ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "Country: %s", personRecord.Country ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "Phone: %s", personRecord.Phone ); printLB(Form1->ListBox1, tmpBuf); sprintf(tmpBuf, "" ); printLB(Form1->ListBox1, tmpBuf); } } /* perform a stat operation to populate the create buffer */ memset(&fileCreateBuf, 0, sizeof(fileCreateBuf)); dataLen = sizeof(fileCreateBuf); keyNum = (BTI_WORD)-1; status = BTRVID(B_STAT, posBlock1, &fileCreateBuf, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); if (status == B_NO_ERROR) { /* create and open sample2.btr */ keyNum = 0; dataLen = sizeof(fileCreateBuf); status = BTRVID(B_CREATE, posBlock2, &fileCreateBuf, &dataLen, keyBuf2, keyNum, (BTI_BUFFER_PTR)&clientID); sprintf(tmpBuf, "Btrieve B_CREATE status = %d", status ); printLB(Form1->ListBox1, tmpBuf); } if (status == B_NO_ERROR) { keyNum = 0; dataLen = 0; status = BTRVID( B_OPEN, posBlock2, dataBuf, &dataLen, keyBuf2, keyNum, (BTI_BUFFER_PTR)&clientID); sprintf(tmpBuf, "Btrieve B_OPEN status = %d", status ); printLB(Form1->ListBox1, tmpBuf); if (status == B_NO_ERROR) { file2Open = TRUE; } } /* now extract data from original file, insert into new one */ if (status == B_NO_ERROR) { /* getFirst to establish currency */ keyNum = 2; /* STATE-CITY index */ memset(&personRecord, 0, sizeof(personRecord)); memset(&keyBuf2[0], 0, sizeof(keyBuf2)); dataLen = sizeof(personRecord); getStatus = BTRVID( B_GET_FIRST, posBlock1, &personRecord, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); sprintf(tmpBuf, "Btrieve B_GET_FIRST status = %d", getStatus ); printLB(Form1->ListBox1, tmpBuf); } gneBuffer = (GNE_BUFFER_PTR)malloc(sizeof(GNE_BUFFER)); if (gneBuffer == NULL) { strcpy(tmpBuf, "Insufficient memory to allocate buffer" ); printLB(Form1->ListBox1, tmpBuf); return(EXIT_WITH_ERROR); } memset(gneBuffer, 0, sizeof(GNE_BUFFER)); memcpy(&gneBuffer->preBuf.gneHeader.currencyConst[0], "UC", 2); while (getStatus == B_NO_ERROR) { gneBuffer->preBuf.gneHeader.rejectCount = 0; gneBuffer->preBuf.gneHeader.numberTerms = 2; posCtr = sizeof(GNE_HEADER); /* fill in the first condition */ gneBuffer->preBuf.term1.fieldType = 11; gneBuffer->preBuf.term1.fieldLen = 3; gneBuffer->preBuf.term1.fieldOffset = 108; gneBuffer->preBuf.term1.comparisonCode = 1; gneBuffer->preBuf.term1.connector = 2; memcpy(&gneBuffer->preBuf.term1.value[0], "TX", 2); posCtr += sizeof(TERM_HEADER); /* fill in the second condition */ gneBuffer->preBuf.term2.fieldType = 11; gneBuffer->preBuf.term2.fieldLen = 3; gneBuffer->preBuf.term2.fieldOffset = 108; gneBuffer->preBuf.term2.comparisonCode = 1; gneBuffer->preBuf.term2.connector = 0; memcpy(&gneBuffer->preBuf.term2.value[0], "CA", 2); posCtr += sizeof(TERM_HEADER); /* fill in the projection header to retrieve whole record */ gneBuffer->preBuf.retrieval.maxRecsToRetrieve = 20; gneBuffer->preBuf.retrieval.noFieldsToRetrieve = 1; posCtr += sizeof(RETRIEVAL_HEADER); gneBuffer->preBuf.recordRet.fieldLen = sizeof(PERSON_STRUCT); gneBuffer->preBuf.recordRet.fieldOffset = 0; posCtr += sizeof(FIELD_RETRIEVAL_HEADER); gneBuffer->preBuf.gneHeader.descriptionLen = posCtr; dataLen = sizeof(GNE_BUFFER); getStatus = BTRVID( B_GET_NEXT_EXTENDED, posBlock1, gneBuffer, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); sprintf(tmpBuf, "Btrieve B_GET_NEXT_EXTENDED status = %d", getStatus ); printLB(Form1->ListBox1, tmpBuf); /* Get Next Extended can reach end of file and still return */ /* some records */ if ((getStatus == B_NO_ERROR) || (getStatus == B_END_OF_FILE)) { sprintf(tmpBuf, "GetNextExtended returned %d records.", gneBuffer->postBuf.numReturned); printLB(Form1->ListBox1, tmpBuf); for (i = 0; i < gneBuffer->postBuf.numReturned; i++) { dataLen = sizeof(PERSON_STRUCT); memcpy(dataBuf, &gneBuffer-> postBuf.recs[i].personRecord, dataLen); status = BTRVID( B_INSERT, posBlock2, dataBuf, &dataLen, keyBuf2, -1, /* no currency change */ (BTI_BUFFER_PTR)&clientID); } sprintf(tmpBuf, "Inserted %d records in new file, status = %d", gneBuffer->postBuf.numReturned, status); printLB(Form1->ListBox1, tmpBuf); } memset(gneBuffer, 0, sizeof(GNE_BUFFER)); memcpy(&gneBuffer->preBuf.gneHeader.currencyConst[0], "EG", 2); } free(gneBuffer); gneBuffer = NULL; /* close open files */ if (file1Open) { dataLen = 0; status = BTRVID( B_CLOSE, posBlock1, dataBuf, &dataLen, keyBuf1, keyNum, (BTI_BUFFER_PTR)&clientID); sprintf(tmpBuf, "Btrieve B_CLOSE status (sample.btr) = %d", status ); printLB(Form1->ListBox1, tmpBuf); } if (file2Open) { dataLen = 0; status = BTRVID( B_CLOSE, posBlock2, dataBuf, &dataLen, keyBuf2, keyNum, (BTI_BUFFER_PTR)&clientID); sprintf(tmpBuf, "Btrieve B_CLOSE status (sample2.btr) = %d", status ); printLB(Form1->ListBox1, tmpBuf); } return(status); }
|
Chapter contents
Prev topic: Language Interfaces for the Btrieve API
|