- Code: Select all Expand view
- #include "Fivewin.ch"
FUNCTION MAIN()
TEST()
RETURN NIL
#pragma BEGINDUMP
#include "hbapi.h"
HB_FUNC( TEST )
{
hb_parvc();
}
#pragma ENDDUMP
EMG
#include "Fivewin.ch"
FUNCTION MAIN()
TEST()
RETURN NIL
#pragma BEGINDUMP
#include "hbapi.h"
HB_FUNC( TEST )
{
hb_parvc();
}
#pragma ENDDUMP
int hb_parvni( int iParam, int n )
{
return hb_parni( iParam, n );
}
LONG hb_parvnl( int iParam, int n )
{
return hb_parnl( iParam, n );
}
const char * hb_parvc( int iParam, int n )
{
return hb_parc( iParam, n );
}
void hb_storvnl( LONG lValue, int iParam, int n )
{
hb_stornl( lValue, iParam, n );
}
void hb_storvl( int iLogical, int iParam, int n )
{
hb_storl( iLogical, iParam, n );
}
void hb_storvni( int iValue, int iParam, int n )
{
hb_storni( iValue, iParam, n );
}
void hb_storvc( const char * szText, int iParam, int n )
{
hb_storc( szText, iParam, n );
}
### C LEVEL COMPATIBILITY ###
===================================
The main difference between Harbour and xHarbour in public C API
is in value quantifiers. Harbour fully respect 'const' variable
attribute and does not remove it from returned values. It helps to
keep code clean and locate places where string constant values
are overwritten what is illegal. It also helps C compiler to better
optimize the code because it has additional information that some
variables/memory regions are readonly and cannot be modified during
code execution what can give some additional speed improvement.
If some C code does not respect it then during compilation with
Harbour header files C compilers usually generate warning and
C++ ones errors, i.e. code like:
char * pszValue = hb_parc( 1 );
is wrong because hb_parc() returns pointer to readonly strings
which cannot be changed by user code. So this code should be
changed to:
const char * pszValue = hb_parc( 1 );
Now if compiled code tries to make sth like:
pszValue[ index ] = 'X';
what is illegal in Harbour, xHarbour and also in Clipper for pointers
returned by _parc() function then compiler generate warning or error
about writing to readonly location.
In summary it means that Harbour forces to keep code clean and use
more strict declarations but xHarbour and Clipper don't and wrong
code can be silently compiled without any warnings or errors.
The second important difference is in hb_par*() and hb_stor*() functions.
In Harbour there are hb_parv*() and hb_storv*() functions which accepts
parameters like in Clipper _par*() and _stor*() functions with optional
array indexes, i.e.:
const char * pszValue = hb_parvc( 1, 1 );
int iValue = hb_parvni( 1, 2 );
and functions without 'v' which do not allow to access array items, i.e.:
const char * pszValue = hb_parc( 1 );
int iValue = hb_parni( 2 );
These functions (without 'v') are also much more restrictive on accepted
parameters and do not make hidden parameter translations, i.e. hb_parl()
returns TRUE only for logical parameters and does not accept numeric
values like hb_parvl() or _parl().
New functions without array index support were introduced to safely access
parameters without strict type checking. Such code:
HB_FUNC( NOT )
{
int iValue = _parni( 1 );
hb_retni( ~iValue );
}
is not fully safe when array parameter is passed from .prg level, i.e.
? NOT( { 5, 4, 7 } )
In such case the behavior is unpredictable because _parni() function
tries to access from C function frame unexciting parameter with array
index. Depending on used hardware (CPU) different things may happen.
On some platforms _parni( 1 ) always return 0, on some other random
value from the array and on some others with hardware function frame
protection it generates exception and application crash. To make the
above code safe programmer should change it to:
HB_FUNC( NOT )
{
int iValue = ISNUM( 1 ) ? _parni( 1 ) : 0;
hb_retni( ~iValue );
}
or:
HB_FUNC( NOT )
{
int iValue = _parni( 1, 0 );
hb_retni( ~iValue );
}
xHarbour does not have hb_par*() and hb_stor*() functions without
optional array index parameters so they cannot be safely used to
access parameters without type checking. It may also create problems
when xHarbour code is moved to Harbour because hb_par*() and
hb_stor*() functions in xHarbour work like hb_parv*() and hb_storv*()
in Harbour. It can be seen in code like:
int iValue = hb_parni( 1, 1 );
C compiler refuses to compile such code with Harbour header files
and it has to be modified to:
int iValue = hb_parvni( 1, 1 );
For portable code which access array items using hb_par/hb_stor API
I suggest to use hb_parv*() and hb_storv*() functions and add in
some header file:
#ifdef __XHARBOUR__
#define hb_parvc hb_parc
#define hb_parvni hb_parni
[...]
#define hb_storvc hb_storc
#define hb_storvni hb_storni
[...]
#endif
or use Clipper compatible functions defined in extend.api: _par*()
and _stor*().
I hope that in the future xHarbour will have above #define translation
in core code or maybe even support for hb_parv*() and hb_storv*() functions.
Next important difference between Harbour and xHarbour is access to internal
HVM structures. In Harbour internal HVM structures are hidden by default so
programmers cannot access them, i.e. PHB_ITEM is mapped as 'void *' pointer
so code like:
iValue = pItem->item.asInteger.value;
cannot be compiled and programmers should change it to use official API:
iValue = hb_itemGetNI( pItem );
It's very important for core developers because public and internal C API
is separated so we can easy introduce modifications in HVM internals without
worrying about backward compatibility and it allows to keep the same code
for different HVM versions (i.e. for MT and ST modes) so in Harbour only
HBVM library is different for MT mode and all others are the same.
Such separation also greatly increase C code quality eliminating possible
GPF traps, wrong behavior in code created without enough knowledge about
HVM internals or code which blocks adding new extensions.
It's sth what should be done in xHarbour core code where lot of code is
simply wrong due to direct access to HVM internals, i.e.
source/rtl/txtline.c[299]:
Term[i] = (char *) (&Opt)->item.asString.value;
and we have GPF trap if given array item is not a string.
source/rtl/version[108]:
PHB_ITEM pQuery = hb_param( 1, HB_IT_INTEGER );
[...]
if( pQuery )
{
int iQuery = pQuery->item.asInteger.value;
[...]
so it does not work if passed numeric parameter is not internally stored
as HB_IT_INTEGER value and programmer cannot control it yourself, i.e.
parameters can be read from table or passed from remote client and then
after deserialization stored as HB_IT_LONG or HB_IT_DOUBLE.
source/rtl/direct.c[124]:
HB_ITEM_NEW( SubDir );
hb_fsDirectory( &SubDir, szSubdir, szAttributes, FALSE, TRUE );
hb_fsDirectoryCrawler( &SubDir, pResult, szFName, szAttributes, sRegEx );
This code creates complex item (array) on C stack so garbage collector does
not know anything about it so it cannot be activated otherwise it will cause
GPF. It means that this code blocks adding automatic garbage collector
activation in memory manager.
These are only examples and anyone can find many other similar problems
in xHarbour core code so in my opinion API separation with core code
cleanup is sth what has to be done in xHarbour in the future.
Of course such separation does not mean that we can forbid 3-rd party
programmers to access HVM internals. Programmers creating code for Harbour
can include before any other Harbour header files "hbvmint.h", i.e.:
#include "hbvmint.h"
#include "hbapi.h"
and it enable access to HVM internals anyhow in such case we do not
guaranty that such code will work in the future Harbour versions so
we strongly recommend to not use it.
In Harbour core code only HBVM library is compiled with access to
HVM internals. All other code uses official API. In contrib code
"hbvmint.h" is used in few places in XHB library to emulate some core
HVM xHarbour extensions.
In xHarbour there are few functions which allows to create string items
without terminating '\0' characters like: hb_itemPutCRaw(),
hb_itemPutCRawStatic(), hb_retclenAdoptRaw(). Because string items
without terminating '\0' character exploit problems in any C code which
needs ASCIIZ string creating possible GPF traps in all str*() and similar
functions then in Harbour such functionality is illegal and will never
be added to core code. Additionally in Harbour functions corresponding to
xHarbour functions: hb_retclenStatic(). hb_itemPutCLStatic() have additional
protection against creating such strings and generate internal error when
programmer tries to pass wrong strings without trailing '\0' character.
It may exploit problems in wrong code ported to Harbour.
Most of other public C functions in Harbour and xHarbour are compatible
anyhow there are some differences i.e. in hash array or timestamp API
which have to be covered by #ifdef __XHARBOUR__ conditional compilation.
Programmers creating portable code have to now about them.
For people who wants to use only extended API for code used for Clipper
and [x]Harbour I suggest to use small definition:
#ifndef __HARBOUR__
#define HB_FUNC( fun ) CLIPPER fun ( void )
#endif
This definition allows to easy create code which can be compiled with
Clipper and Harbour or xHarbour header files (extend.api).
It can be even added to Clipper's extend.api and then we can compile
this code:
#include "extend.api"
HB_FUNC( NOT )
{
int iValue = _parni( 1, 0 );
hb_retni( ~iValue );
}
for Clipper, Harbour and xHarbour. Please only remember that linkers
used with [x]Harbour are case sensitive and always use upper letters
for function names. In Clipper it was not necessary.
carlos vargas wrote:Enrico, this api no exist in xharbour.
carlos vargas wrote:The main difference between Harbour and xHarbour in public C API
is in value quantifiers. Harbour fully respect 'const' variable
attribute and does not remove it from returned values. It helps to
keep code clean and locate places where string constant values
are overwritten what is illegal.
Error E2141 clipmor.c 7: Declaration syntax error
Error E2209 clipzip.c 5: Unable to open include file 'wizzip.h'
Error E2209 clipzip.c 6: Unable to open include file 'ClipZip.h'
Error E2141 clipzip.c 19: Declaration syntax error
Error E2209 clipzip2.c 4: Unable to open include file 'ClipZip.h'
Error E2141 clipzip2.c 7: Declaration syntax error
Error E2141 cpuid.c 131: Declaration syntax error
Error E2342 fgetline.c 171: Type mismatch in parameter '__s' (wanted 'const signed char *', got 'int') in function HB_FUN_HEIGHTFLINE
Error E2342 fgetline.c 366: Type mismatch in parameter '__s' (wanted 'const signed char *', got 'int') in function HB_FUN__DRAWFGETLINE
Error E2342 fgetline.c 714: Type mismatch in parameter '__s' (wanted 'const signed char *', got 'int') in function HB_FUN_FORMATFLINE
Error E2342 foldtool.c 91: Type mismatch in parameter 'lpString' (wanted 'const signed char *', got 'int') in function HB_FUN_FOLDPAINT
Error E2342 foldtool.c 297: Type mismatch in parameter 'lpString' (wanted 'const signed char *', got 'int') in function HB_FUN_FOLDPAINT
Error E2141 hash.c 13: Declaration syntax error
Error E2141 keyboard.c 7: Declaration syntax error
Error E2141 monitor.c 8: Declaration syntax error
Error E2209 msgs.c 10: Unable to open include file 'hbapicls.h'
Error E2141 ntxpos.c 167: Declaration syntax error
Error E2141 say3d.c 17: Declaration syntax error
Error E2139 symtabl.c 9: Declaration missing ;
Error E2141 symtabl.c 20: Declaration syntax error
Error E2141 tabstool.c 15: Declaration syntax error
Error E2209 treedraw.c 15: Unable to open include file 'fwHarb.h'
Error E2451 treedraw.c 236: Undefined symbol 'OBJECT' in function HB_FUN_LBSETDATA
Error E2451 treedraw.c 241: Undefined symbol 'PCLIPVAR' in function HB_FUN_LBGETDATA
Error E2379 treedraw.c 241: Statement missing ; in function HB_FUN_LBGETDATA
Error E2451 treedraw.c 249: Undefined symbol 'p' in function HB_FUN_LBGETDATA
Error E2209 unzip.c 4: Unable to open include file 'Info-unz.h'
Error E2209 unzip.c 5: Unable to open include file 'FwMsgs.h'
Error E2141 unzip.c 9: Declaration syntax error
Error E2141 unzip.c 45: Declaration syntax error
char * hb_parvc( int iParam, int iIndex )
{
return ( char * ) hb_parc( iParam, iIndex );
}
Antonio Linares wrote:Enrico,
You have to use Harbour header files (and not xHarbour ones) to recompile FWH C modules
Antonio Linares wrote:Enrico,
Please review FWH source\function\harbour.prg and you will see how we compatibilize Harbour and xHarbour APIs
i.e.:
- Code: Select all Expand view
char * hb_parvc( int iParam, int iIndex )
{
return ( char * ) hb_parc( iParam, iIndex );
}
Antonio Linares wrote:If you include those prototypes inside your hbapi.h, then it should compile fine
Return to FiveWin for Harbour/xHarbour
Users browsing this forum: Google [Bot] and 100 guests