From b0f4f1f4a1de91cf5978f85b85942235f2e81c83 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Mon, 15 Feb 2010 09:05:58 +0000 Subject: [PATCH] 2010-02-15 10:05 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbvm.h * harbour/src/vm/hvm.c + added new C function hb_vmFindFuncSym() which looks for function with given name registered in HVM by dynamically loaded library. It looks for public function and if public function cannot be located it tries to find first static function which has requested name. * harbour/include/hbapi.h * harbour/src/vm/dynlibhb.c + added new C functions to manage dynamic libraries: PHB_ITEM hb_libLoad( PHB_ITEM pLibName, PHB_ITEM pArgs ); HB_BOOL hb_libFree( PHB_ITEM pDynLib ); void * hb_libHandle( PHB_ITEM pDynLib ); void * hb_libSymAddr( PHB_ITEM pDynLib, const char * pszSymbol ); * harbour/include/hbextern.ch * harbour/src/vm/dynlibhb.c - removed HB_LIBDO() PRG function. If someone used it then please use DO() instead + added new PRG function: HB_LIBGETFUNSYM( , ) -> | NIL It works in similar way to HB_HRBGETFUNSYM() but it looks for PRG function in given library. It tries to find public function and if such function does not exists it looks for first static one. is library handle returned by HB_LIBLOAD() is PRG function name. is symbol of located function If function can be found HB_LIBGETFUNSYM() returns NIL. Warning: this function returns only symbols for functions registered in HVM when library was loaded. It will not return symbols for functions written in C and not explicitly registered using own symbol table. --- harbour/ChangeLog | 34 ++++++++++++ harbour/include/hbapi.h | 4 ++ harbour/include/hbextern.ch | 2 +- harbour/include/hbvm.h | 1 + harbour/src/vm/dynlibhb.c | 104 +++++++++++++++++++++++++----------- harbour/src/vm/hvm.c | 35 ++++++++++++ 6 files changed, 149 insertions(+), 31 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 9c319c73e6..f2e901fc78 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,40 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-02-15 10:05 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbvm.h + * harbour/src/vm/hvm.c + + added new C function hb_vmFindFuncSym() which looks for function with + given name registered in HVM by dynamically loaded library. It looks + for public function and if public function cannot be located it tries + to find first static function which has requested name. + + * harbour/include/hbapi.h + * harbour/src/vm/dynlibhb.c + + added new C functions to manage dynamic libraries: + PHB_ITEM hb_libLoad( PHB_ITEM pLibName, PHB_ITEM pArgs ); + HB_BOOL hb_libFree( PHB_ITEM pDynLib ); + void * hb_libHandle( PHB_ITEM pDynLib ); + void * hb_libSymAddr( PHB_ITEM pDynLib, const char * pszSymbol ); + + * harbour/include/hbextern.ch + * harbour/src/vm/dynlibhb.c + - removed HB_LIBDO() PRG function. If someone used it then please + use DO() instead + + added new PRG function: + HB_LIBGETFUNSYM( , ) -> | NIL + It works in similar way to HB_HRBGETFUNSYM() but it looks for + PRG function in given library. It tries to find public function + and if such function does not exists it looks for first static one. + is library handle returned by HB_LIBLOAD() + is PRG function name. + is symbol of located function + If function can be found HB_LIBGETFUNSYM() returns NIL. + Warning: this function returns only symbols for functions registered + in HVM when library was loaded. It will not return symbols + for functions written in C and not explicitly registered + using own symbol table. + 2010-02-14 17:34 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) * contrib/gtwvg/wvgscrlb.prg ! Defined method :configure() as VIRTUAL. diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index c4b8d05455..c075f5dbc8 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -1106,6 +1106,10 @@ extern HB_EXPORT void hb_vmSetDefaultGT( const char * szGtName ); extern HB_EXPORT PHB_FUNC hb_vmProcAddress( const char * szFuncName ); +extern HB_EXPORT PHB_ITEM hb_libLoad( PHB_ITEM pLibName, PHB_ITEM pArgs ); +extern HB_EXPORT HB_BOOL hb_libFree( PHB_ITEM pDynLib ); +extern HB_EXPORT void * hb_libHandle( PHB_ITEM pDynLib ); +extern HB_EXPORT void * hb_libSymAddr( PHB_ITEM pDynLib, const char * pszSymbol ); /* misc */ extern HB_EXPORT const char * hb_verCPU( void ); /* retrieves a constant string with CPU architecture */ diff --git a/harbour/include/hbextern.ch b/harbour/include/hbextern.ch index 4a03a26ae5..f2a8360796 100644 --- a/harbour/include/hbextern.ch +++ b/harbour/include/hbextern.ch @@ -958,7 +958,7 @@ EXTERNAL HB_HRBGETFUNSYM EXTERNAL HB_LIBLOAD EXTERNAL HB_LIBFREE -EXTERNAL HB_LIBDO +EXTERNAL HB_LIBGETFUNSYM EXTERNAL HB_LIBERROR EXTERNAL HB_RANDOM diff --git a/harbour/include/hbvm.h b/harbour/include/hbvm.h index b219a619bc..da9fd8d4bc 100644 --- a/harbour/include/hbvm.h +++ b/harbour/include/hbvm.h @@ -101,6 +101,7 @@ extern HB_EXPORT PHB_SYMB hb_vmProcessDynLibSymbols( PHB_SYMB pSymbols, HB_USHOR extern void hb_vmBeginSymbolGroup( void * hDynLib, HB_BOOL fClone ); extern void hb_vmInitSymbolGroup( void * hNewDynLib, int argc, const char * argv[] ); extern void hb_vmExitSymbolGroup( void * hDynLib ); + extern PHB_SYMB hb_vmFindFuncSym( const char * szFuncName, void * hDynLib ); extern const char * hb_vmFindModuleSymbolName( PHB_SYMB pSym ); extern HB_BOOL hb_vmFindModuleSymbols( PHB_SYMB pSym, PHB_SYMB * pSymbols, HB_USHORT * puiSymbols ); extern PHB_SYMB hb_vmGetRealFuncSym( PHB_SYMB pSym ); diff --git a/harbour/src/vm/dynlibhb.c b/harbour/src/vm/dynlibhb.c index 24aa222b1e..07691148a9 100644 --- a/harbour/src/vm/dynlibhb.c +++ b/harbour/src/vm/dynlibhb.c @@ -93,20 +93,20 @@ static const HB_GC_FUNCS s_gcDynlibFuncs = hb_gcDummyMark }; -HB_FUNC( HB_LIBLOAD ) +PHB_ITEM hb_libLoad( PHB_ITEM pLibName, PHB_ITEM pArgs ) { void * hDynLib = NULL; - if( hb_parclen( 1 ) > 0 ) + if( hb_itemGetCLen( pLibName ) > 0 ) { - int argc = hb_pcount() - 1, i; + int argc = pArgs ? ( int ) hb_arrayLen( pArgs ) : 0, i; const char ** argv = NULL; if( argc > 0 ) { argv = ( const char** ) hb_xgrab( sizeof( char* ) * argc ); for( i = 0; i < argc; ++i ) - argv[i] = hb_parcx( i + 2 ); + argv[ i ] = hb_arrayGetCPtr( pArgs, i + 1 ); } if( hb_vmLockModuleSymbols() ) @@ -117,7 +117,7 @@ HB_FUNC( HB_LIBLOAD ) { void * hFileName; - hDynLib = ( void * ) LoadLibrary( HB_PARSTR( 1, &hFileName, NULL ) ); + hDynLib = ( void * ) LoadLibrary( HB_ITEMGETSTR( pLibName, &hFileName, NULL ) ); hb_strfree( hFileName ); } @@ -126,11 +126,11 @@ HB_FUNC( HB_LIBLOAD ) HB_UCHAR LoadError[ 256 ] = ""; /* Area for load failure information */ HMODULE hDynModule; if( DosLoadModule( ( PSZ ) LoadError, sizeof( LoadError ), - ( PCSZ ) hb_parc( 1 ), &hDynModule ) == NO_ERROR ) + ( PCSZ ) hb_itemGetCPtr( pLibName ), &hDynModule ) == NO_ERROR ) hDynLib = ( void * ) hDynModule; } #elif defined( HB_HAS_DLFCN ) - hDynLib = ( void * ) dlopen( hb_parc( 1 ), RTLD_LAZY | RTLD_GLOBAL ); + hDynLib = ( void * ) dlopen( hb_itemGetCPtr( pLibName ), RTLD_LAZY | RTLD_GLOBAL ); #else { int iTODO; @@ -150,16 +150,16 @@ HB_FUNC( HB_LIBLOAD ) { void ** pLibPtr = ( void ** ) hb_gcAllocate( sizeof( void * ), &s_gcDynlibFuncs ); * pLibPtr = hDynLib; - hb_retptrGC( pLibPtr ); + return hb_itemPutPtrGC( NULL, pLibPtr ); } - else - hb_ret(); + + return NULL; } -HB_FUNC( HB_LIBFREE ) +HB_BOOL hb_libFree( PHB_ITEM pDynLib ) { HB_BOOL fResult = HB_FALSE; - void ** pDynLibPtr = ( void ** ) hb_parptrGC( &s_gcDynlibFuncs, 1 ); + void ** pDynLibPtr = ( void ** ) hb_itemGetPtrGC( pDynLib, &s_gcDynlibFuncs ); if( pDynLibPtr && *pDynLibPtr && hb_vmLockModuleSymbols() ) @@ -179,7 +179,57 @@ HB_FUNC( HB_LIBFREE ) } hb_vmUnlockModuleSymbols(); } - hb_retl( fResult ); + + return fResult; +} + +void * hb_libHandle( PHB_ITEM pDynLib ) +{ + void ** pDynLibPtr = ( void ** ) hb_itemGetPtrGC( pDynLib, &s_gcDynlibFuncs ); + + return pDynLibPtr ? *pDynLibPtr : NULL; +} + +void * hb_libSymAddr( PHB_ITEM pDynLib, const char * pszSymbol ) +{ + void * hDynLib = hb_libHandle( pDynLib ); + + if( hDynLib ) + { +#if defined( HB_OS_WIN ) + return ( void * ) GetProcAddress( ( HMODULE ) hDynLib, pszSymbol ); +#elif defined( HB_OS_OS2 ) + PFN pProcAddr = NULL; + if( DosQueryProcAddr( ( HMODULE ) hDynLib, 0, pszSymbol, &pProcAddr ) == NO_ERROR ) + return ( void * ) pProcAddr; +#elif defined( HB_HAS_DLFCN ) + return dlsym( hDynLib, pszSymbol ); +#endif + } + return NULL; +} + +HB_FUNC( HB_LIBLOAD ) +{ + int iPCount = hb_pcount(), i; + PHB_ITEM pArgs = NULL; + + if( iPCount > 1 ) + { + pArgs = hb_itemArrayNew( iPCount - 1 ); + for( i = 2; i <= iPCount; ++i ) + hb_arraySet( pArgs, i, hb_param( i, HB_IT_ANY ) ); + } + + hb_itemReturnRelease( hb_libLoad( hb_param( 1, HB_IT_ANY ), pArgs ) ); + + if( pArgs ) + hb_itemRelease( pArgs ); +} + +HB_FUNC( HB_LIBFREE ) +{ + hb_retl( hb_libFree( hb_param( 1, HB_IT_ANY ) ) ); } HB_FUNC( HB_LIBERROR ) @@ -191,29 +241,23 @@ HB_FUNC( HB_LIBERROR ) #endif } -/* Executes a Harbour pcode dynamically loaded DLL function or procedure - * Syntax: HB_libDo( [,] ) --> [] +/* Get FUNCTION or PROCEDURE symbol from given library. + * hb_libGetFunSym( , ) -> | NIL */ - -HB_FUNC( HB_LIBDO ) +HB_FUNC( HB_LIBGETFUNSYM ) { - if( hb_parclen( 1 ) > 0 ) + const char * szFuncName = hb_parc( 2 ); + + if( szFuncName ) { - PHB_DYNS pDynSym = hb_dynsymFindName( hb_parc( 1 ) ); + void * hDynLib = hb_libHandle( hb_param( 1, HB_IT_ANY ) ); - if( pDynSym ) + if( hDynLib ) { - int iPCount = hb_pcount(); - int iParam; + PHB_SYMB pSym = hb_vmFindFuncSym( szFuncName, hDynLib ); - hb_vmPushSymbol( pDynSym->pSymbol ); - hb_vmPushNil(); - - /* same logic here as from HB_FUNC( EVAL ) */ - for( iParam = 2; iParam <= iPCount; iParam++ ) - hb_vmPush( hb_stackItemFromBase( iParam ) ); - - hb_vmProc( ( HB_USHORT ) ( iPCount - 1 ) ); + if( pSym ) + hb_itemPutSymbol( hb_stackReturnItem(), pSym ); } } } diff --git a/harbour/src/vm/hvm.c b/harbour/src/vm/hvm.c index 45bde58e83..7b89539c8e 100644 --- a/harbour/src/vm/hvm.c +++ b/harbour/src/vm/hvm.c @@ -7326,6 +7326,41 @@ HB_BOOL hb_vmFindModuleSymbols( PHB_SYMB pSym, PHB_SYMB * pSymbols, return HB_FALSE; } +PHB_SYMB hb_vmFindFuncSym( const char * szFuncName, void * hDynLib ) +{ + static PHB_SYMB pFuncSym = NULL; + + if( szFuncName ) + { + PHB_SYMBOLS pSymbols = s_pSymbols; + + while( pSymbols ) + { + if( pSymbols->hDynLib == hDynLib ) + { + HB_USHORT ui; + + for( ui = 0; ui < pSymbols->uiModuleSymbols; ++ui ) + { + PHB_SYMB pSymbol = &pSymbols->pModuleSymbols[ ui ]; + + if( ( pSymbol->scope.value & HB_FS_LOCAL ) != 0 && + hb_stricmp( pSymbol->szName, szFuncName ) == 0 ) + { + if( ( pSymbol->scope.value & HB_FS_STATIC ) == 0 ) + return pSymbol; + else if( ! pFuncSym ) + pFuncSym = pSymbol; + } + } + } + pSymbols = pSymbols->pNext; + } + } + + return pFuncSym; +} + #define HB_SYM_STATICSBASE( p ) \ ( ( PHB_ITEM ) ( ( (p)->scope.value & HB_FS_FRAME ) ? \ (p)->value.pStaticsBase : NULL ) )