Importing class from dll

Hi

My problem is that I cannot import a class from a dll without an import library.

Thank You,
Attila.



Answer this question

Importing class from dll

  • iproetel

    Ebaoll wrote:
    I have found another problem.
    When calling a function from my dll ( not in a class, just a function ), I am getting the following error message:

    Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

    I found out, that it is related to __fastcall, __stdcall and __cdecl. But I don't use these! I don't know what to do with this.

    Could you show the definition of the exported function please



  • jrboddie

    I have written the dll. And there is a function called GetProcAddress, that i can use for importing functions from a dll, and this way, i don't need a lib file. But I want to import a class, and that i cannot do with this function (or at least I don't know how to).

    But thanx anyway.

    Attila

  • johncart

    Just a few more details:
    I have found, and can use LoadLibrary, GetProcAddress etc. functions, but only for importing functions.

    What is the name of the function I should use instead of
    GetProcAddress for importing classes from my dll

    thanx, Attila

  • telackey

    A little more information on this and maybe you will understand why classes cannot be exported easily by using GetProcAddress.

    For a class like this.

    class __declspec(dllexport) newclass
    {
    private:
     int a;
    public:
     newclass(void);
     ~newclass(void);
     void test(void);
     void seta(int);
     int geta();
    };

    Dumpbin actually reports the following as being exported. So to be able to export a class you will actually have to do things like that yourself.

    Microsoft (R) COFF/PE Dumper Version 8.00.50727.42 Copyright (C) Microsoft Corporation.  All rights reserved.


    Dump of file testdll2.dll

    File Type: DLL

      Section contains the following exports for testdll2.dll

        00000000 characteristics
        4415CD4E time date stamp Mon Mar 13 19:51:42 2006
            0.00 version
               1 ordinal base
               6 number of functions
               6 number of names

        ordinal hint RVA      name

              1    0 0001101E 0newclass@@QAE@XZ = @ILT+25( 0newclass@@QAE@XZ)
              2    1 0001116D 1newclass@@QAE@XZ = @ILT+360( 1newclass@@QAE@XZ)
              3    2 000110C8 4newclass@@QAEAAV0@ABV0@@Z = @ILT+195( 4newclass@@QAEAAV0@ABV0@@Z)
              4    3 00011131 geta@newclass@@QAEHXZ = @ILT+300( geta@newclass@@QAEHXZ)
              5    4 000110DC seta@newclass@@QAEXH@Z = @ILT+215( seta@newclass@@QAEXH@Z)
              6    5 000110FF test@newclass@@QAEXXZ = @ILT+250( test@newclass@@QAEXXZ)

      Summary

            1000 .data
            1000 .idata
            2000 .rdata
            1000 .reloc
            1000 .rsrc
            4000 .text
           10000 .textbss

    I think the best idea though is to not actually export a class, but export the functions and do a wrapper class around the functions. That will give you the same functionality that you want.

    To make this absolutely clear. There is no function to export classes. If you notice above the class is exported by exporting ALL of the functions individually and then sticking them together as a class when the program itself is compiled. There is nothing you can do to try and fix this at all because this is the way it works.



  • G. Miller

    This is down to the calling convention that the function uses. For example.

    int __stdcall Function1(int a, int b);

    This uses the stdcall calling convention.

    The calling convention is important because of how the function itself starts and finishes, this is called the prolog and epilog of the function. It behaves differently for different conventions.

    Since you are using GetProcAddress to get the address of the function you need to specify in the function pointer the calling convention if it is different from the default, but I find it easier to be doubly sure and put it in anyway.

    For the above function you would need to have your function pointer as following.

    int (__stdcall *function)(int, int);

    Otherwise it could use a different calling convention and you will get the errors that you are recieving.

    I think it uses __cdecl by default for normal functions but I'm not sure other than that.



  • mad Mazz

    I have found another problem.
    When calling a function from my dll ( not in a class, just a function ), I am getting the following error message:

    Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

    I found out, that it is related to __fastcall, __stdcall and __cdecl. But I don't use these! I don't know what to do with this.

  • PuTeFabiO

    the dll:

    #include <stdio.h>
    #include <windows.h>

    #include <iostream>
    #include <conio.h>

    using namespace std;

    extern "C" __declspec(dllexport)
    int writeSerialPort(int numberOfBytesToWrite, char* data, unsigned long *bytes_sent){

    HANDLE serialPort;
    serialPort = CreateFile( TEXT("com1"), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
    if (serialPort==INVALID_HANDLE_VALUE) {
    return 1;
    }

    if (!WriteFile(serialPort, (void *)data, 1, bytes_sent, NULL)) {
    CloseHandle(serialPort);
    return 2;
    }

    CloseHandle(serialPort);
    return 0;
    }

    the exe, that uses this dll:

    #include <windows.h>
    #include <iostream>
    #include <stdio.h>
    #include <conio.h>

    using namespace std;

    typedef int (WINAPI* _writeSerialPort)(int numberOfBytesToWrite, char* data, unsigned long *bytes_sent);
    _writeSerialPort writeSerialPort;

    void main() {

    HINSTANCE hLib=LoadLibrary(TEXT("serial.dll"));
    if(hLib==NULL) {

    cout << "Unable to load library!" << endl;
    getch();
    return;
    }

    writeSerialPort=(_writeSerialPort)GetProcAddress((HMODULE)hLib, "writeSerialPort");

    if (writeSerialPort==NULL) {
    cout << "Unable to load function(s)." << endl;
    FreeLibrary((HMODULE)hLib);
    return;
    }

    char* data="asd";
    unsigned long bytes_sent;

    cout << writeSerialPort(1,data, &bytes_sent);
    FreeLibrary((HMODULE)hLib);

    getch();
    }

  • Art Gaisin

    So there is no function like GetProcAddress for classes

  • A. A.

    But he also needs the header file where the class is defined so it can make calls at development time and create instances of that class. Static Libraries (.lib) are used at linking time (after the compiler finishes) so you can not create your exported class just using the .lib file because you don't know how to create it.

    If you only have a .dll and there are classes inside you want to use, there is no way to use them if you don't have the definition because this is the layout your program needs to know to make instances properly.

    If you were using COM, this problem can be solved using Interfaces because in COM technology you can instance classes inside a .dll through Class Factories. Those class factories receive an empty double pointer to an interface (because it returns a pointer to the vtable or a pointer to pointers) your class implements and some identifiers (class and interface identifiers), so it can locate, create, cast and fill the interface pointer you requested. To communicate with COM objects you can use the universal marshaler (IDispatch for scripting and non-scripting languages) and a custom interface (faster and based in vtables) it depends on your choice.

    If you were just using exported function from a .dll, is enough just calling LoadLibrary and make calls to GetProcAddress with the proper name or ordinal value to access those methods, but that is not the case with classes.

    =)

     

     



  • dagma20

    Theres your problem.

    extern "C" __declspec(dllexport)
    int writeSerialPort(int numberOfBytesToWrite, char* data, unsigned long *bytes_sent)

    typedef int (WINAPI* _writeSerialPort)(int numberOfBytesToWrite, char* data, unsigned long *bytes_sent);
    _writeSerialPort writeSerialPort;

    In the exe you have it as WINAPI which is a synonym for __stdcall. In the dll you don't have anything so its __cdecl. So you either need to remove WINAPI from the exe or add it to the dll as follows.

    extern "C" __declspec(dllexport)
    int WINAPI writeSerialPort(int numberOfBytesToWrite, char* data, unsigned long *bytes_sent)



  • KennS

    You should have been given a lib file to go with the DLL. If you weren't given this file, ask the guys who wrote the dll to give you one.

  • R&amp;#233;mi

    If you are the one who wrote the dll then you should export the classes by using __declspec(dllexport) and linking with the lib file that is created. This should be the only way to export classes from a dll file..

    GetProcAddress, as its name implies, can only get procedure addresses notany other kinds.

    It is actually easier not to use GetProcAddress when using dll files anyway.



  • He Hua

    I removed WINAPI, and now it works.

    typedef int (* _writeSerialPort)(int numberOfBytesToWrite, char* data, unsigned long *bytes_sent);

    but there is still one problem:

    Untill now, the program worked, only the debugger stopped it with that error message. So it sad it wrote 1 byte to the serial port, or it wrote there is no serial port.

    Now it says it writes 1 byte, although there is NO SERIAL PORT on this computer.

    Any ideas

  • smilek

    Ebaoll wrote:
    So there is no function like GetProcAddress for classes

    See http://msdn2.microsoft.com/en-us/library/81h27t8c.aspx



  • Importing class from dll