DLL's, Borland & alot of Frustrations

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Airslash
    New Member
    • Nov 2007
    • 221

    DLL's, Borland & alot of Frustrations

    Hi,

    I'm sorry if this is not the correct forum, but since I'm programming in C++ this looked like the best place.

    I'm trying to make a nice DLL file for the company where we place all functions, classes and definitions in it to share amongst our various software projects.
    These things are written in C++.

    At the moment I havent done anything special yet to the files suchas including those magic __ words for the export etc.

    We are using CodeGears Borland C++ builder as main development IDE.
    Our first test was to put our GDI+ wrapper in the DLL and call it from one of our projects.

    But we have some issues getting the DLL linked.
    Can anyone provide me with a explanation as to what needs to be done in order to make the C++ classes inside the DLL exportable and to link the DLL to our projects using Borland CodeGears?



    this IDE is driving me nuts.....in VS its just a few clicks to get it sorted....
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    You are using Windows, yes?

    First decide on where you are going to use explicit or implicit linking.

    Explicit linking means you will call LoadLibrary to loas the DLL and then call GetProcAddress for the address of your function in the DLL and then you will call the function at that address.

    Implicit linking means you will call the DLL function as you would any other function. Here you use the .h file created by the DLL build. The function you call in that .h does the LoadLibrary, the GetProcAddress and the call to the function at that address. This implicit linking requires a _dllimport in the .h file function prototype. If this is not there, then you have to use explicit linking.

    Maybe you could explain further about your linking issue.

    Comment

    • Airslash
      New Member
      • Nov 2007
      • 221

      #3
      Yes,
      We're developing for Windows Server 2003 at the moment.

      The basic idea is to have one DLL where all the classes, structs and functions are that are commonly shared between the various small applications that we develop.
      An example I recently developed would be a GDI+ wrapper.

      At the moment I have created the header and class file for this wrapped and placed them inside the DLL project. Nothing else in it at the moment.

      The idea now is that when I create a new application, I can simply type for example:

      Code:
      Wrapper x = new Namespace::Wrapper();
      Without having to worry about all the required files for this class, since they're all in the DLL and beeing linked for the Project.
      What I would like to know, do I need to add anything speciall to the class definitions inside the DLL or in the Project.

      We've been trying several things with the #define and #pragma statements in a project, and the project compiled, but as soon as we called one of the classes/functions from the DLL the application refused to run or even start up at some point.

      Comment

      • weaknessforcats
        Recognized Expert Expert
        • Mar 2007
        • 9214

        #4
        First, all the code in the DLL can be in C++ except the functions you call from your program.

        A DLL is an old C whiz-bang where you use the name of the DLL funcrtion in your program:

        Code:
        FARPROC ptr = GetProcAddress(hModule, "AreaOfSquare");
        Unfortunately, AreaOfSquare is never found in the DLL. The C++ compiler has mangled the name in the DLL. Therfore, the function in the DLL must be extern "C":

        Code:
        //In the DLL:
        extern "C"
        int __stdcall AreaOfSquare(int len, int wid)
        {
             ACplusplusFunction();
        }
        The ACplusplus function does not need to be extern "C" since it is never called using a literal "ACplusplus ".

        So, your DLL interface must be designed correctly.

        The extern "C" can be avoided by using a DEF file to export the mangled name as an alias:

        Code:
        ;BEGIN ADLL.DEF FILE
        ;This DEF file is required becuase the argument to GetProcAddress()
        ;for the function is a C-string and it will never be equal to the
        ;C++ mangled name for the function
        ;This DEF file maps the mangled name to a name that can be used with GetProcAddress()
        ;Note also: Change project settings in Visual Studio to send the LINK this def file.
        ;Visual Studio.NET: Project Properties/Linker/Input/Module Definition File/...Path to the def file\Adll.def
        LIBRARY ADll 
        EXPORTS 
        ;Exported Name    C++ Mangled Name
        AreaOfSquare   =  ?AreaOfSquare@@YGHHH@Z
        DisplayFromDll =  ?DisplayFromDll@@YGXXZ
        ;END DEF
        FILE

        Lastly, the DLL export functions must use the __stdcall convention (WINAPI).

        If you use GetProcAddress and you are successful in getting a non-null FARPROC returned, I would typecast that pointer into a function pointer of the correct type. That way when I call the DLL function inside my program, I can just use the name that was coded inthe DLL in the first place:

        Code:
        FARPROC ptr = GetProcAddress(hModule, "AreaOfSquare");
        int (__stdcall *AreaOfSquare)(int, int);
        	//Type-cast the address returned from GetProcAddress to the function pointer type
        	AreaOfSquare = reinterpret_cast<int (__stdcall*)(int,int)>  (addr);
        cout << "The area of a 6x8 square is " << AreaOfSquare(6,8) << endl;

        Comment

        • Airslash
          New Member
          • Nov 2007
          • 221

          #5
          woah,

          complex :)


          But if I understand it correctly, I need to make some kind of C function that for example fetches my C++ class for me, and that should work without a problem then ?

          Comment

          • RRick
            Recognized Expert Contributor
            • Feb 2007
            • 463

            #6
            I have worked a little bit with DLLs and found that they have issues with what can cross between the DLL library to your application.

            For example, if something is newed in the DLL, then it needs to be deleted in the DLL. STL containers in the DLL have issues when accessed/modified by your app.

            I'm not sure of the specifics and this was a while ago. Perhaps someone else can clarify these issues.

            Comment

            • weaknessforcats
              Recognized Expert Expert
              • Mar 2007
              • 9214

              #7
              It's not that complex.

              I would get a copy of Windows via C/C++ by Jeffrey Richter where all this is documented.

              But yes, you write a function in the DLL that is called by the program. That function can create C++ objects, call member functions, etc. But the name of this function cannot be mangled. That's because you are asking for the funciton by name (a literal) in the GetProcAddress call. If the compiler has mangled the name in the DLL, then the mangled name will never match the literal in the GetProcAddress call. Therefore the function must be extern"C" in the DLL code.

              Please note: Bacause the DLL is compiled in C++ and the interfacing functions are called like C functions, you are quite OK to use this C++ DLL in a hard C program. Heck if that C program interfaces FORTRAN, you can access C++ code from FORTRAN programs.

              I have attached a ZIP for a DLL example that works in Visual Studio.NET 2008. Compile using a DLL project.
              Attached Files

              Comment

              • Airslash
                New Member
                • Nov 2007
                • 221

                #8
                Alright,

                I'll definitly give it a look when I'm back at work (23.00 while writing this).
                Been looking around a bit more on the Internet regarding the whole stuff of DLLs and doubting a bit whether or not I should make a static .lib instead of the dynamic .dll file.

                Most things are still a big mystery to me on this subject since I'm only a junior C++ not so long graduated, but have to bite the bullet sometime.

                Definitly big thanks for the replies.
                Still got a load of questions and probably will run into more problems, but at least I have a better understanding of the whole subject.

                Comment

                • weaknessforcats
                  Recognized Expert Expert
                  • Mar 2007
                  • 9214

                  #9
                  A static lib will make your program larger and removes the ability to change the program by just chaing the DLL. Often it's easier to keep the main installed base and just produce new DLL versions for your upgrades.

                  Also, your program could read a .ini file and in there could be the name of the DLL to use. This allows your program to chnage the name of the DLL that's loaded without changing the code.

                  Try, always, to have no hard-coded assumptions in that main program.

                  A Visual Studio. NET DLL project produces both a .dll and .lib. The difference is that if your use the .lib, the function there calls LoadLibrary, GetProcAddress and the function in the DLL. This is the implicit linking. You will notice a __dllimport in the .h file.

                  Comment

                  • Airslash
                    New Member
                    • Nov 2007
                    • 221

                    #10
                    Well,

                    we solved the problem finnally.
                    Call me a nunchkimpoop but the problem was that the application couldn't find the DLL and the Borland Debugger wasn't smart enough to tell us so.

                    We found out by running the compiled exe files outside the IDE and then got the missing DLL error.
                    Now everything is working as it should and the DLL is working like a charm.

                    Even have classes in it without C function calls, just plain C++ stuff that can be called without problems. Was a bit tricky to get the __dllexport and __dllimport stuff in the right places, but all works.

                    a new thing learned :)

                    Comment

                    • weaknessforcats
                      Recognized Expert Expert
                      • Mar 2007
                      • 9214

                      #11
                      That's great.

                      This is an example of no knowledge gained unless you first experience the necessary tears.

                      The necessary tears occur at 1:30am after a week of 16 hour days and you finally explode and throw your keyboard through your monitor, tears streaming down your face, shouting "Why doesn't this %%*($%^ thing compile!!!".

                      At this point you reach a teachable moment.

                      No one escapes.

                      Comment

                      • Airslash
                        New Member
                        • Nov 2007
                        • 221

                        #12
                        it's also why I like the language so much. Or programming in General.

                        When you think you've found the solution, some ugly bug appears or something else goes wrong.
                        There's always a challenge.

                        Comment

                        Working...