On Fri, 08 Jan 2010, francesco perillo wrote:
Hi,
> At the end of March I asked in this newsgroup if it was possible to
> check if a function was present (linked) in an exe during run-time.
> The answer was to use TYPE() and check if the result is UI or U....
> I did this yesterday on my notebook and it worked... now on my dev pc it
> doesn't work.... I allways get UI....
TYPE() works perfectly. It's enough to know what it does.
TYPE( funcname + "()" )
checks if function is registered in global function table and if not
then it returns "U".
If it exists then it checks if it's one of core functions with reserved
name (see src/common/reserved.c). If not then it returns "UI" otherwise
it tries to execute <funcname>() and return type of result ("C", "D",
"L", ...) or "UE" if error appeared during execution.
That's all.
So if you want to check if given UDF function exists it's enough to make
TYPE( funcname + "()" ) == "UI"
but if you want to check also for functions from reseved function list
then the problem is more complicated. If the function called without
parameter does not return NIL then you can test:
! TYPE( funcname + "()" ) == "U"
> So I created this little piece of code, studying the HB_ExecFromArray code:
> HB_FUNC( ISLINKED )
> {
> char * szString = hb_parc( 1 ) ;
> if ( hb_dynsymFindName( szString ) )
> hb_retl( TRUE ) ;
> else
> hb_retl( FALSE ) ;
> }
This code does not give any information if function exists. It only
checks is symbol is register in global symbol table what is not usable
information in this context. It retrns the same results as this .prg
code:
func ISLINKED( s )
return __DYNSGETINDEX( s ) != 0
> Now you can use
> IsLinked( "FUNC" )
This code shows that above ISLINKED() function does not work correctly
and may return wrong results.
proc main()
private variable
? 'ISLINKED( "islinked" )"', IsLinked( "islinked" )
? '!TYPE( "islinked()" ) == "U"', !type( "islinked()" ) == "U"
? 'ISLINKED( "variable" )"', IsLinked( "variable" )
? '!TYPE( "variable()" ) == "U"', !type( "variable()" ) == "U"
?
? 'ISLINKED( "blablabla" )"', IsLinked( "blablabla" )
? '!TYPE( "blablabla()" ) == "U"', !type( "blablabla()" ) == "U"
x := &("{||blablabla()}")
? 'ISLINKED( "blablabla" )"', IsLinked( "blablabla" )
? '!TYPE( "blablabla()" ) == "U"', !type( "blablabla()" ) == "U"
?
? '!TYPE( "str()" ) == "U"', !type( "date()" ) == "U"
? '!TYPE( "date()" ) == "U"', !type( "str()" ) == "U"
return
#pragma begindump
#include "hbapi.h"
HB_FUNC( ISLINKED )
{
const char * szString = hb_parc( 1 ) ;
if ( hb_dynsymFindName( szString ) )
hb_retl( TRUE ) ;
else
hb_retl( FALSE ) ;
}
#pragma enddump
The correct version should look like:
func ISLINKED( s )
local n := __DYNSGETINDEX( s )
return n != 0 .and. __DYNSISFUN( n )
It's enough for ST mode. In MT mode you have to remember that
indexes can change change when new symbols are added to symbol
table so you should add additional protection to above code
and repeat check if index changed after comparison.
BTW We can add extension to __DYNSISFUN() so it will accept also
function name as 1-st parameter not only index.
And please do not write that TYPE() does not work correctly without
self contain example which gives different results then Clipper because
such messages are usually only source of some incredible myths about
Clipper and Harbour behavior and we have to fight with them for years ;-)
best regards,
Przemek
_______________________________________________
Harbour mailing list (attachment size limit: 40KB)
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour