c++c++builderstdcallc++builder-xe2owlnext

c++-builder: convert into stdcall type


I'm currently trying to port an old owl-c++-builder-projekt to use XE2 and owlnext. In the old file, I could simply call a line

(FARPROC)LP_I2COpen = GetProcAddress(Hi_I2C, "I2COpen");

While LP_I2Open is defined with

#ifdef WIN32
#define CALLING_CONVENTION  __stdcall
#else
#define CALLING_CONVENTION  far pascal
#endif

int CALLING_CONVENTION (*LP_I2COpen)(HWND hndl,HINSTANCE hInstance, struct I2C_PROP far *ps);

#ifdef _WIN64
typedef INT_PTR (FAR WINAPI *FARPROC)();
#else
typedef int (FAR WINAPI *FARPROC)();
#endif

WINBASEAPI FARPROC WINAPI GetProcAddress(... 

Those code-blocks are actually from multiple files. I thought this order would be intuitive.

Now I have some difficulties to rewrite this as needed. I understand, that now the left side is understood as a converting-method giving a value back, but can't be assigned to a specific value, so a "L-Value expected"-error is thrown. However, I don't quite know how to convert the FARPROC into something that would fit into LP_I2COpen... Trying without any convertions throws this error:

[BCC32 Fehler] Dio.cpp(2906): E2034 Konvertierung von 'int (__stdcall *)()' nach 'int (__stdcall *)(HWND__ *,HINSTANCE__ *,I2C_PROP *)' nicht möglich

So, does anybody know which mistakes I'm doing with this line?

(FARPROC)LP_I2COpen = GetProcAddress(Hi_I2C, "I2COpen");

Regards, Julian


Solution

  • Casting l-values is invalid, and AFAIK it has always been invalid, although some compilers accepted it. Technically, you create a temporary of type FARPROC which then gets assigned the result of GetProcAddress() before being discarded. The correct way looks like this:

    // function type alias
    typedef int CALLINGCONVENTION I2COpenFn(HWND, HINSTANCE, I2C_PROP*);
    // read and convert function pointer
    I2COpenFn* LP_I2COpen = (I2COpenFn*)GetProcAddress(Hi_I2C, "I2COpen");
    

    Note that things like "far" are obsolete. Also note that this C-style cast is ugly, but you don't have any type safety anyway and it's isolated to a restricted amount of code. If you can though, use proper linking instead of loading the DLL at runtime.