Specific APIs:spc

Example for building a C-API project Foundation

This section demonstrates how to use the C-API within your projects. An example is discussed in detail showing the different steps required to compile your C-sources and link them to an Xbase++ application.

Requirements

Make sure you have installed the Xbase++ C-API correctly.

The following files must be located in a directory listed in your INCLUDE-path.

xppdef.h, xppcon.h, xpppar.h 

You need Microsoft Visual-C++ Version 4.0 or higher.

You need IBM VisualAge-C++ Version 3.0 or higher.

Also make sure that the directories of your C-compiler are correctly listed in the PATH, LIB and INCLUDE environment variables.

Preparation

Create a makefile to build both the Xbase++ source and the C-source and link the two resulting OBJ files. The makefile includes the following instructions:

CC=cl /c /Zl /Tc  
LINK=alink /DE 

sample.exe: sample.obj f2bin.obj 
    $(LINK) sample.obj f2bin.obj 

sample.obj: sample.prg 
     xpp /b /q $* 

f2bin.obj: f2bin.c 
     $(CC) f2bin.c 

Now you can write your C-API functions

In the example, any numeric value is converted to an 8-Byte-binary string and vice versa. The code in the file F2BIN.C looks like this:

#include <windows.h> 

#include "xppdef.h" 
#include "xpppar.h" 
#include "xppcon.h" 

#ifdef _MSC_VER 
int _fltused; 
#endif 

#define MAXLEN 8 
/* this is the "little secret": 
 * treat the memory of a double 
 * like a string with 8 bytes (and the terminating 0) 
 */ 
typedef union { 
   double dbl; 
   char string[MAXLEN+1]; 
} F2BinBuffer; 

/* 
 * Create a binary string from a numeric 
 * 
 * F2BIN(nNumber) => c8Binary  
 */ 
XPPRET XPPENTRY F2BIN(XppParamList paramList) { 
   ContainerHandle chResult = _conNew(NULLCONTAINER); 
   F2BinBuffer valBuffer={0}; 
   if ( XPP_IS_NUM( _partype( paramList, 1) ) ) { 
      valBuffer.dbl = _parnd( paramList, 1); 
   } 
   else { 
      // return a 0-filled buffer if any errors 
      valBuffer.dbl = 0.0; 
   } 
   _conPutCL( chResult, valBuffer.string, MAXLEN );     
   _conReturn( paramList, chResult); 
   _conRelease( chResult); 
   return; 
} 

/* 
 * reverse the binary string to a numeric 
 * 
 * BIN2F(c8Binary) => nNumber (0 if any parameter errors) 
 */ 
XPPRET XPPENTRY BIN2F(XppParamList paramList) { 
   F2BinBuffer valBuffer={0}; 
   if ( XPP_IS_CHAR( _partype( paramList, 1) ) ) { 
      _parc( valBuffer.string, MAXLEN+1, paramList, 1 ); 
   } 
   _retnd( paramList, valBuffer.dbl); 
   return; 
} 

Use the functions in your Xbase++ code

The C-compiler mangles __cdecl function names with a preceding underscore. Therefore, you must map the function names in your Xbase++ code to match the actual C-function names (refer to the next section for details about #pragma map). The following Xbase++ code tests the C-functions F2Bin() and Bin2F() (file SAMPLE.PRG):

#pragma map(F2BIN,"_F2BIN") 
#pragma map(BIN2F,"_BIN2F") 

PROCEDURE Main 
   LOCAL nNumber, cTemp 

   /* XPP_DOUBLE - Test */ 
   nNumber := 100.234e16 
   ? nNumber 
   cTemp := F2Bin(nNumber) 
   nNumber := Bin2F(cTemp) 
   ? nNumber 

   /* XPP_NUMERIC - Test */ 
   nNumber := 45345 
   ? nNumber 
   cTemp := F2Bin(nNumber) 
   nNumber := Bin2F(cTemp) 
   ? nNumber 
RETURN 

Build the project

To build the project you enter on the command line:

make -f <name of makefile> 

Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.