Here's some OLD docs on the process. Might not help much, but could at
least light the way...
Goldstar Software Inc.
Building on Btrieve(R) for the Future(SM)
Bill Bach
BillB...@compuserve.com
www.goldstarsoftware.com
*** Pervasive.SQL Service & Support Classes ***
See our web site for details!
Source Code Example of Thunking
Filename: THUNK.WRI
Version: 10/97
Btrieve Technologies provides 16 bit DLLS for the OS/2 environment for the
Btrieve and XQL product lines. The most popular OS/2 compilers are IBM
CSET/2, IBM CSET/2++, Borland C++, and Watcom. All of these compilers are
32 bit compilers. In order to use any of the above mentioned products with
these compilers, header files and source must be changed to reflect the
conversion between the 32 bit world and the 16 bit world. This process is
called THUNKING.
All 32 bit Compilers supply documentation and help for the process of
Thunking. The CSET/2 2.0 compiler documents this process in the CSET
Application Design Guide manual in Chapter 3.
The typical terminology associated with thunking are things such as:
1) Declaration of 16 bit pointers..... char * _Seg16 databuffer
2) Declaration of 16 bit functions ... _Far16 _Pascal func(short, char 8)
3) The use of 16 bit PRAGMAS ......... #pragma seg16 (of_a_structure)
Some compilers have predefined #define declarations for 16 bit pointers.
With the CSET compiler types such as CHAR and UCHAR are defined in OSDEF.h
as:
typedef UCHAR * _Seg16 PUCHAR16;
typedef CHAR * _Seg16 PCHAR16;
Consequently, when some examples are used they will take advantage of
COMPILER DEFINED terms.
Beyond pointer conversion, application developers need to keep in mind that
when they are looking at 16 bit code or header files, things such as 'long'
or 'int' can be stored physically different in the 32 bit environment.
For example, in the 16 bit storage schema an 'int' is 2 bytes, in the 32
bit storage schema an 'int' is 4 bytes. These differences can affect the
stack greatly. A 16 bit DLL is only going to want two bytes of data on the
stack. Understanding the relationship between the 16 bit compilers and the
32 bit compilers storage mechanisms helps to determine the changes that are
neccessary. Data types should be used that reflect storage dimensions and
will be consistent regardless of the storage schema being used. For
instance, the 'short' data type indicates two bytes, regardless of the
schema. Again, these are all elements defined by the specific compilers in
use and the use of such data types as 'short' is a standard set by the C
language itself.
These differences should be accounted for in defining structures as well.
Applications that have structures that are based upon integer and long
definitions may need to be altered to use the 16 bit version of the data
type. As always make sure that the compiler's packing option is set to
byte align. (the infamous /Zp1)
The following is a Btrieve example that uses the Seg16 terminology to do
the 'thunking'.
=========================================================================
#include <stdio.h>
#include <os2.h>
#include <string.h>
#define B_Open 0
#define B_Close 1
#define B_GetFirst 12
typedef CHAR BTR_CHAR;
#pragma seg16(BTR_CHAR)
#pragma linkage(btrcall, far16 pascal)
#pragma linkage(btrvinit, far16 pascal)
extern SHORT btrcall(short,char * _Seg16, char * _Seg16, short * _Seg16,
char * _Seg16, BYTE, CHAR);
extern SHORT btrvinit(char * _Seg16);
extern SHORT BTRINIT(CHAR *);
extern SHORT BTRV(SHORT, CHAR *, CHAR *, SHORT *, CHAR *, SHORT);
main()
{
char databuf[512];
SHORT dblen = 0;
SHORT status;
char PosBlock[128];
char KeyBuffer[512];
char InitBuf[100];
strcpy(InitBuf, "/p:4096 /m:40 ");
status = BTRINIT(InitBuf);
printf("status = %d\n", status);
strcpy(KeyBuffer, "Test.btr ");
status = BTRV(B_Open, PosBlock, databuf, &dblen, KeyBuffer, 1);
printf("status = %d\n", status);
dblen=sizeof(databuf);
status = BTRV(B_GetFirst, PosBlock, databuf, &dblen, KeyBuffer, 0);
printf("status = %d\n", status);
status = BTRV(B_Close, PosBlock, databuf, &dblen, KeyBuffer, 1);
printf("status = %d\n", status);
}
/* Call to the Btrieve OS/2 dynamic link */
/* library from the BTRV call */
SHORT BTRV (SHORT operation, CHAR *posblock, CHAR *databuf, SHORT *datalen,
CHAR *keybuf, SHORT keynum)
{
BYTE keylen = 255;
CHAR ckeynum = keynum;
CHAR * _Seg16 posblock16, * _Seg16 databuf16, * _Seg16 keybuf16;
SHORT * _Seg16 datalen16;
posblock16 = posblock;
databuf16 = databuf;
datalen16 = datalen;
keybuf16 = keybuf;
return (btrcall (operation, posblock16, databuf16, datalen16, keybuf16,
keylen, ckeynum));
}
SHORT BTRINIT( CHAR *initbuf)
{
CHAR * _Seg16 initbuf16;
initbuf16 = initbuf;
return (btrvinit (initbuf16));
}
===========================================================================
Here is a Btrieve example that uses CSET predefined type declarations
instead of the _Seg16 macro and linkage pragmas.
==========================================================================
#include <os2.h>
#include <stdio.h>
#include <string.h>
#define B_Open 0
#define B_Close 1
#define B_GetFirst 12
extern USHORT _Far16 _Pascal BTRCALL (USHORT, PSZ, PSZ, PUSHORT, PSZ, BYTE,
CHAR);
extern USHORT _Far16 _Pascal BTRVINIT (PSZ);
extern USHORT _Far16 _Pascal BTRVSTOP (void);
extern USHORT _Far16 _Pascal BRQSHELLINIT (PSZ);
USHORT BTRV(USHORT, PSZ, PSZ, PUSHORT, PSZ, SHORT);
main()
{
UCHAR databuf[512];
USHORT dblen = 0;
USHORT status;
UCHAR PosBlock[128];
UCHAR KeyBuffer[512];
strcpy(KeyBuffer, "Test.btr ");
status = BTRV(B_Open, PosBlock, databuf, &dblen, KeyBuffer, 1);
printf("open status = %d\n", status);
dblen=sizeof(databuf);
status = BTRV(B_GetFirst, PosBlock, databuf, &dblen, KeyBuffer, 0);
printf("get status = %d\n", status);
status = BTRV(B_Close, PosBlock, databuf, &dblen, KeyBuffer, 1);
printf("close status = %d\n", status);
status = BTRVSTOP();
printf("stop status = %d\n", status);
}
/* Call to the Btrieve OS/2 dynamic link */
/* library from the BTRV call */
USHORT BTRV (USHORT operation, PSZ posblock, PSZ databuf, PUSHORT datalen,
PSZ keybuf, SHORT keynum)
{
BYTE keylen = 255;
CHAR ckeynum = keynum;
return (BTRCALL (operation, posblock, databuf, datalen, keybuf,
keylen, ckeynum));
}
========================================================================
It is important to understand that as compilers change and more 32 bit
compilers are generated for the OS/2 and NT platforms that 'THUNKING' is a
directive of the compiler, not the 16 bit code being used and will be
commonplace until vendors can create 32-bit code. All compiler
documentation should provide information on how to thunk functions and
variables.
Uwe Labs wrote:
> Hello,
> I am write school administration software, which used to use Btrieve
> 6.10 on a Novell Server. Since schools don't have much money, I would
> like to use Btrieve 6 further on (because it comes with Netware) but
> with a 32-Bit-Delphi-Application which runs on Win 95/98/NT/2000
> (instead of my old DOS application).
> So I have to use the old Windows-3-DLL wbtrcall.dll to call the
> Btrieve-6-engine on the Novell server.
> This implies that I have to use the Microsoft thunking mechanism to get
> the calls along DLL-32 and DLL-16.
> Does anyone has this already worked out ? And would explain this in
> details to me ?
> This would be very nice !
> Regards, Uwe Labs.
> (I hope this message is not deleted by any of the Pervasive people. I
> know, it is not the stategy of Pervasive to use this method. But as I
> outlined, schools don't have money. So this method would help at least
> for some time).