• Welcome to Powerbasic Museum 2020-B.
 

News:

Forum in repository mode. No new members allowed.

Main Menu

Dynamic API calls

Started by Gérôme Guillemin, February 04, 2009, 11:32:54 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Gérôme Guillemin

Hello,

For those that are interested in Dynamic API call, I wrote years ago a simple API Call layer that was used into AutoHotkey scripting language and co.
Here's the C code MSVC++ and LCC WIn32 compatible (may be adapted for GCC) :


//--------------------------------------------------------------------------------
//Author : Gerome GUILLEMIN
//Dynamic API :: the ultimate code !   
//--------------------------------------------------------------------------------
//!!!!!!!!!!!! POWER !!!!!!!!!!!!
//If you appreciate this sample code, please register to FBSL 
//Enjoy and take care 
//--------------------------------------------------------------------------------

//  Examples :

/*
   CallDllFx("Sleep","kernel32",1, 1000);
   CallDllFx("SleepEx","kernel32",2, 2000, 1);
   CallDllFx("WritePrivateProfileString","kernel32", 4, "Section1", "SecondKey", "By golly, it works.", "c:\\appname.ini");
*/

// C implementation:

int WINAPI CallDllFx (char *FuncName, char *DllName, int nArgs, ...)
{
HINSTANCE  hInst = 0;
FARPROC lpAddr    = 0;
int arg    = 0;
int result = 0;
char buff[128] = {'\0'};
va_list ap;
int argtable[128]; //[nArgs]; // in LCC WIN32 because of the Dynamic Support !
   
   memset( &argtable, 0, sizeof(argtable) );

   hInst=GetModuleHandle(DllName);
   if(hInst==NULL) {
      hInst=LoadLibrary(DllName);
   }
   else {
      //DBS( "(0)Library '%s' already loaded !", DllName );
   }
   lpAddr=(FARPROC)GetProcAddress(hInst,FuncName);
   if(lpAddr==NULL) {
      sprintf(buff,"%s%s",FuncName,"A");
      lpAddr=(FARPROC)GetProcAddress(hInst,buff);
   }
   if(lpAddr==NULL) {
      sprintf(buff,"%s%s","_",FuncName);
      lpAddr=(FARPROC)GetProcAddress(hInst,buff);
   }
   if (lpAddr) {
      va_start(ap,nArgs);
      for (register int i=0; i<nArgs;i++) {
         arg = va_arg(ap,int);
         argtable[i] = arg;
      }
      for (register int ii=nArgs-1;ii >=0; ii--) {
         arg = argtable[ii];
      }
      va_end( ap );
      __try {
         result = lpAddr();
      } __except ( EXCEPTION_EXECUTE_HANDLER ) {
         if (hInst) FreeLibrary(hInst);
         return -1;
      }

   }

   if(hInst) FreeLibrary(hInst);

return result;
}


Enjoy !

Theo Gottwald

Looks interesting, does somebody have this as PB-Code?

Patrice Terrier

#2
Theo,

This is the same technic being used in WinDev (PC-Soft) to call a DLL from their WL p-code.

It is not that hard to translate to PB ;)

Here is a small example, i wrote many years ago to encapsulate the first version of BASS.DLL


    hBassDll??? = LoadLibrary("BASS.DLL")
    IF hBassDll??? THEN
       hBassWmaDll??? = LoadLibrary("BASSWMA.DLL")
       pBassPtr = GetProcAddress(hBassDll???, "BASS_GetVersion")
       IF pBassPtr THEN
          CALL DWORD pBassPtr USING BASS_GetVersion TO Ret???
          Version$ = TRIM$(STR$(LOWRD(Ret???))) + "." + TRIM$(STR$(HIWRD(Ret???)))
       END IF
       BassVer& = VAL(Version$) * 10
       IF BassVer& >= 18 THEN ' Basscd.dll requires at leats BASDLL version 1.8
          hBassEncodeDll??? = LoadLibrary("BASSENC.DLL")
          hBassCdDll??? = LoadLibrary("BASSCD.DLL")
          IF BassVer& >= 20 THEN ' Basscd.dll requires at leats BASDLL version 1.8
             hBassVisDll??? = LoadLibrary("BASS_VIS.DLL")
          END IF
       END IF
    END IF
 

Added:
For the optional parameters, there is an ASM source code somewhere in POFF showing how to pass multiple parameters, that was done to work arround the PB6 or PB7 limitation of passing more than 16 parameters.

And for the current version, see the use of the "optional" keyword.
Quote
Using classic optional parameters

When declaring a CDECL SUB or FUNCTION, you can specify trailing parameters as optional, using a set of brackets [..]:

DECLARE SUB KerPlunk CDECL (x%, y% [, z%])

Note that the comma separating the y% parameter from the optional z% parameter is inside the brackets.  The following calling sequences would then be valid:

CALL KerPlunk (x%, y%)

CALL KerPlunk (x%, y%, z%)

Optional parameters must be the last parameters designated in the list.
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Eros Olmi

thinBasic Script Interpreter - www.thinbasic.com | www.thinbasic.com/community
Win7Pro 64bit - 8GB Ram - Intel i7 M620 2.67GHz - NVIDIA Quadro FX1800M 1GB