Home > Back-end >  Different calling conventions in a same plain C function
Different calling conventions in a same plain C function

Time:09-06

I'm a harbour programmer and I need know how I can use different calling conventions in a same plain C function, because some DLL manufacturer use __stdcall and another use __cdecl but the functions are the same, example:

static int iCcv = 1;

HB_FUNC( foo )
{
   if( iCcv == 1 )
      typedef const char * ( __stdcall * pMYFUNC )( int n );
   else
      typedef const char * ( __cdecl * pMYFUNC )( int n );

   pMYFUNC funcMy = (pMYFUNC) GetProcAddress( hLib, "myProc" );

   const char * ret;

   if( funcMy )
       ret = funcMy( hb_parni( 1 ) );

   hb_retc( ret );
}

CodePudding user response:

You need something more like:

const int CALLING_STDCALL=1;
const int CALLING_CDECL=2;

typedef const char * ( __stdcall * pMYFUNC_STDCALL )( int n );
typedef const char * ( __cdecl * pMYFUNC_CDECL )( int n );

 //... The init() function where the library is linked...
 int init(FARPROC* my_func){
     *my_func=GetProcAddress( hLib, "myProc" );
     if(*my_func==NULL){
         return -1;
     }
     return 0; //Always check you loaded successfully!
 } 

//.. to call it

const char *CallMyFunc(FARPROC pFunc,int n,int conv){
    assert(pFunc!=NULL);//Should never get this far badly loaded.
    if(conv==STDCALL){
        pMYFUNC_STDCALL func=(pMYFUNC_STDCALL)pFunc;
        return pFunc(n);
    }
    assert(conv==CALLING_CDECL);//Good measure!
    pMYFUNC_CDECL func=(pMYFUNC_CDECL)pFunc;
    return pFunc(n);
}

The 'magic' here is that the code to call both conventions will be generated and the relevant version executed (assuming the flag was set correctly somehow - that wasn't in the question!).

There's not quite such a thing as a generic function-pointer (though you can round-trip function-pointers between function-pointer types) and there is no guarantee in C that void * will do(*). But on the Windows Platform FARPROC is provided for that purpose. Behaviour is defined in the platform for casting FARPROC to the correct type.

The above would benefit from a bit more type-safety by wrapping the pointer in a safety struct but I think that might bury the essence here.

Please. Please! Do put in a good dose of error checking and maybe elevate my debug asserts() to permanent release build checks.

Having worked at a place where things were a mountain of peripherals and DLLs that didn't always do what they said on their box any help in diagnostics is worth its weight in gold.

(*) though on modern platforms usually does.

  •  Tags:  
  • c
  • Related