Dynamicly calling functions from DLL / C++ / Builder

i have a basic DLL ( generated with C++Builder ) and i want to load that file "dynamicly" without DEF file loading or creating with using LoadLibrary GetProcAddress Casting and FreeLibrary :

// MY DLL Implementation ----
[code]
#include
#include
#include "dllfile.h"

#pragma argsused
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}

EXPORT int __stdcall Function( int a, int b) {
std::cout << "Toplam = " << (a+b) << std::endl;
return 0 ;
}
[/code]
// dllfile.h ------
[code]
#define EXPORT extern "C" __declspec( dllexport )
EXPORT int __stdcall Function( int a, int b) ;
[/code]
I have compiled with no error and i have created a DLL successfully. But when i call my function with console C++ application
[code]
typedef int (__stdcall *ptrFunc) (int, int) ;
ptrFunc Func ;

int main(int argc, char* argv[])
{

HINSTANCE handle = LoadLibrary("mydll.dll") ;
Func = static_cast < ptrFunc > ( GetProcAddress(handle,"Function") );
Func(4,5) ;
return 0;

}
[/code]
the casting error occurs;
[b]E2031: Cannot cast from int (__stdcall *)() to "int (__stdcall *)(int, int)[/b]


Comments

  • : i have a basic DLL ( generated with C++Builder ) and i want to load that file "dynamicly" without DEF file loading or creating with using LoadLibrary GetProcAddress Casting and FreeLibrary :
    :
    : // MY DLL Implementation ----
    : [code]
    : #include
    : #include
    : #include "dllfile.h"
    :
    : #pragma argsused
    : int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
    : {
    : return 1;
    : }
    :
    : EXPORT int __stdcall Function( int a, int b) {
    : std::cout << "Toplam = " << (a+b) << std::endl;
    : return 0 ;
    : }
    : [/code]
    : // dllfile.h ------
    : [code]
    : #define EXPORT extern "C" __declspec( dllexport )
    : EXPORT int __stdcall Function( int a, int b) ;
    : [/code]
    : I have compiled with no error and i have created a DLL successfully. But when i call my function with console C++ application
    : [code]
    : typedef int (__stdcall *ptrFunc) (int, int) ;
    : ptrFunc Func ;
    :
    : int main(int argc, char* argv[])
    : {
    :
    : HINSTANCE handle = LoadLibrary("mydll.dll") ;
    : Func = static_cast < ptrFunc > ( GetProcAddress(handle,"Function") );
    : Func(4,5) ;
    : return 0;
    :
    : }
    : [/code]
    : the casting error occurs;
    : [b]E2031: Cannot cast from int (__stdcall *)() to "int (__stdcall *)(int, int)[/b]
    :
    :
    :

    Casting between different kinds of function pointers is undefined behaviour, at least in C. But nevermind that, and nevermind static_cast either. Just do a normal typecast and it will work fine:

    Func = (ptrFunc) (GetProcAddress(handle,"Function") );
  • : : [code]
    : : typedef int (__stdcall *ptrFunc) (int, int) ;
    : : ptrFunc Func ;
    : :
    : : int main(int argc, char* argv[])
    : : {
    : :
    : : HINSTANCE handle = LoadLibrary("mydll.dll") ;
    : : Func = static_cast < ptrFunc > ( GetProcAddress(handle,"Function") );
    : : Func(4,5) ;
    : : return 0;
    : :
    : : }
    : : [/code]
    : : the casting error occurs;
    : : [b]E2031: Cannot cast from int (__stdcall *)() to "int (__stdcall *)(int, int)[/b]

    : Casting between different kinds of function pointers is undefined behaviour, at least in C. But nevermind that, and nevermind static_cast either. Just do a normal typecast and it will work fine:
    :
    : Func = (ptrFunc) (GetProcAddress(handle,"Function") );

    But Lundin, what causes the compiler to think there are two different kinds of function pointers? They ARE all of the same type? So where did the compiler get the [b]int (__stdcall *)()[/b] from?

    Just curious... Thanks in advance,
    bilderbikkel

  • : : : [code]
    : : : typedef int (__stdcall *ptrFunc) (int, int) ;
    : : : ptrFunc Func ;
    : : :
    : : : int main(int argc, char* argv[])
    : : : {
    : : :
    : : : HINSTANCE handle = LoadLibrary("mydll.dll") ;
    : : : Func = static_cast < ptrFunc > ( GetProcAddress(handle,"Function") );
    : : : Func(4,5) ;
    : : : return 0;
    : : :
    : : : }
    : : : [/code]
    : : : the casting error occurs;
    : : : [b]E2031: Cannot cast from int (__stdcall *)() to "int (__stdcall *)(int, int)[/b]
    :
    : : Casting between different kinds of function pointers is undefined behaviour, at least in C. But nevermind that, and nevermind static_cast either. Just do a normal typecast and it will work fine:
    : :
    : : Func = (ptrFunc) (GetProcAddress(handle,"Function") );
    :
    : But Lundin, what causes the compiler to think there are two different kinds of function pointers? They ARE all of the same type? So where did the compiler get the [b]int (__stdcall *)()[/b] from?
    :
    : Just curious... Thanks in advance,
    : bilderbikkel
    :
    :

    It is the FARPROC type returned from GetProcAddress.

    I can show a little trick I use when importing DLL functions.
    Here is from some code I once wrote:

    [code]
    union
    {
    struct
    {
    void (__stdcall* listener_EnableWarnings)(bool enabled);
    bool (__stdcall* listener_OpenCom)(const char* port, const char* baudrate);
    void (__stdcall* listener_CloseCom)(void);
    void (__stdcall* listener_ShowListener)(int);
    void (__stdcall* listener_KillListener)(void);
    }func;

    void (__stdcall* dsipFunc[N_FUNC])(void);
    }dsipFunctions;

    #define listener_EnableWarnings dsipFunctions.func.listener_EnableWarnings
    #define listener_OpenCom dsipFunctions.func.listener_OpenCom
    #define listener_CloseCom dsipFunctions.func.listener_CloseCom
    #define listener_ShowListener dsipFunctions.func.listener_ShowListener
    #define listener_KillListener dsipFunctions.func.listener_KillListener
    [/code]


    First I list all the different functions in the DLL one by one.
    Then in the same union I list them as an array of function pointers of the same type. After all, they are only 32-bit integers in the end so you know that you can typecast from one function pointer to the other without causing trouble, as long as you use right return type and parameters when you call the actual function.

    This has another advantage as well: I can open all DLL functions in a loop:

    [code]
    for(short i=0; i<N_FUNC; i++)
    {
    dsipFunctions.dsipFunc[i] = (void(__stdcall*)(void)) GetProcAddress(hDLL,funcNames[i]);
    if(dsipFunctions.dsipFunc[i]==NULL)
    {
    std::cerr << "Couldn't find " << funcNames[i] << " in " << DLL_PATH << "." << std::endl;
    return 1;
    }
    }

    [/code]
  • :-)

    See ya,
    bilderbikkel

  • : This has another advantage as well: I can open all DLL functions in
    : a loop:
    :
    : [code]:
    : for(short i=0; i<N_FUNC; i++)
    : {
    : dsipFunctions.dsipFunc[i] = (void(__stdcall*)(void)) GetProcAddress(hDLL,funcNames[i]);
    : if(dsipFunctions.dsipFunc[i]==NULL)
    : {
    : std::cerr << "Couldn't find " << funcNames[i] << " in " << DLL_PATH << "." << std::endl;
    : return 1;
    : }
    : }
    :
    : [/code]:

    Thanks Lundin, that did the trick for the initialization.
    But do you have some hint on the normal calling convention like:

    bool (__stdcall* listener_OpenCom)(const char* port, const char* baudrate);

    How do you use the above mentioned function after the initialization ?

    Thanks a lot.

    Niffarella


  • Woah, this was an old thread.

    Simply call it as you would with any function:

    bool success = listener_OpenCom("COM1", "9600");

    That's why I wrote the #defines at the bottom of that post, they are there to remove the struct/union notation so that the function can be used more conveniently.
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories