Creating DLLs

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • vermarajeev
    New Member
    • Aug 2006
    • 180

    #1

    Creating DLLs

    Hi Banfa also Everbody,
    I'm extremely in help with you guys.

    Please Please it is really urgent to me.

    Problem
    I have two modules in my project 1) CMBEDIT 2) SYNTHESIS_TOOL

    I have these files common between these two modules
    i) ct.h
    ii) ct.cpp
    iii) route.h
    iv) route.cpp
    v) basemolecule.h
    vi) basemolecule.cp p

    No I have to create dll( DYnamic Link Library ) which will act as a repository for those common files.

    When I execute CMBEDIT, it should call (dll) and make use of those files, vice versa When I execute SYNTHESIS_TOOL, it should call same (dll) and make use of those files.

    I'm a newbie in dll areas and this is my first experience...PL ease write the complete instructions to make that happen. I'm using Visual Studio. NET 2003 on my system.

    Please Please reply me as soon as possible. It is really urgent.

    Waiting for a reply.
  • Banfa
    Recognized Expert Expert
    • Feb 2006
    • 9067

    #2
    Right it goes something like this (unfortunately I have access to Visual Studio 6 and Visual Studio 2005 but not 2003 .net so you will have to interpret what I say inteligently)

    In Visual Studio

    1. Start a new project (File -> New... and selct projects from the Tabs)

    2. Select a WIN32 Dynamic Link Library, fillin project name etc. and hit OK

    3. When asked select "a DLL that exports some symbols"

    4. It will create a cpp file with a DLLMain plus some example symbols (an int a basic calss and a function) plus a header file (plus the ubiquitous stdafx.cpp and stdafx.h for precompiled headers)

    5. Do not delete the DLLMain but the example stuff can go once you have understood it.

    6. Include you source files into the project declare symbols to be accessed by the program in the header file following the examples. The important point here is that a symbol that is to be exported must be declared with

    __declspec(dlle xport)

    when compiling the DLL

    and

    __declspec(dlli mport)

    when compiling the program.

    7. Build your DLL. This will result in a .DLL file and a .LIB file

    8. In your program include the DLL header and link with the .LIB file

    9. When you run your program make sure that the DLL file is in the same directory as the EXE or that it is in the path.

    Comment

    • vermarajeev
      New Member
      • Aug 2006
      • 180

      #3
      Originally posted by Banfa
      Right it goes something like this (unfortunately I have access to Visual Studio 6 and Visual Studio 2005 but not 2003 .net so you will have to interpret what I say inteligently)

      In Visual Studio

      1. Start a new project (File -> New... and selct projects from the Tabs)

      2. Select a WIN32 Dynamic Link Library, fillin project name etc. and hit OK

      3. When asked select "a DLL that exports some symbols"

      4. It will create a cpp file with a DLLMain plus some example symbols (an int a basic calss and a function) plus a header file (plus the ubiquitous stdafx.cpp and stdafx.h for precompiled headers)

      5. Do not delete the DLLMain but the example stuff can go once you have understood it.

      6. Include you source files into the project declare symbols to be accessed by the program in the header file following the examples. The important point here is that a symbol that is to be exported must be declared with

      __declspec(dlle xport)

      when compiling the DLL

      and

      __declspec(dlli mport)

      when compiling the program.

      7. Build your DLL. This will result in a .DLL file and a .LIB file

      8. In your program include the DLL header and link with the .LIB file

      9. When you run your program make sure that the DLL file is in the same directory as the EXE or that it is in the path.
      Hi Banfa,
      Thankx for your immediate reply...
      I'm able to follow till steps 5 and got these files
      1) myDll.h
      2) stdafx.h
      3) myDll.cpp
      4) stdafx.cpp
      The output of myDll.cpp seems to be like this

      Code:
      // myDll.cpp : Defines the entry point for the DLL application.
      //
      
      #include "stdafx.h"
      #include "myDll.h"
      BOOL APIENTRY DllMain( HANDLE hModule, 
                             DWORD  ul_reason_for_call, 
                             LPVOID lpReserved
      					 )
      {
      	switch (ul_reason_for_call)
      	{
      	case DLL_PROCESS_ATTACH:
      	case DLL_THREAD_ATTACH:
      	case DLL_THREAD_DETACH:
      	case DLL_PROCESS_DETACH:
      		break;
      	}
          return TRUE;
      }
      
      // This is an example of an exported variable
      MYDLL_API int nmyDll=0;
      
      // This is an example of an exported function.
      MYDLL_API int fnmyDll(void)
      {
      	return 42;
      }
      
      // This is the constructor of a class that has been exported.
      // see myDll.h for the class definition
      CmyDll::CmyDll()
      { 
      	return; 
      }
      Also I have included my common files here as
      Code:
      // stdafx.h : include file for standard system include files,
      // or project specific include files that are used frequently, but
      // are changed infrequently
      //
      
      #pragma once
      
      
      #define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
      // Windows Header Files:
      #include <windows.h>
      
      
      
      // TODO: reference additional headers your program requires here
      #include "common/ct.h"
      #include "common/route.h"
      #include "common/basemolecule.h"
      But the step6 that you mentioned is unclear to me...What symbol are u taking about there?

      Also please tell me what I should do after this....This is my status till now....

      Comment

      • Banfa
        Recognized Expert Expert
        • Feb 2006
        • 9067

        #4
        Step 6

        In your orignal post you mention wanting to put the following files

        i) ct.h
        ii) ct.cpp
        iii) route.h
        iv) route.cpp
        v) basemolecule.h
        vi) basemolecule.cp p

        Into the DLL. These functions contain some symbols (i.e. functions and/or variables.

        It is normal to have a single header for a DLL (although i understand the concept of having a header for every C file in a project) so I said

        "Include you source files into the project declare symbols to be accessed by the program in the header file following the examples. The important point here is that a symbol that is to be exported must be declared with"

        indicating (well trying to anyway :D) that you should include the source files listed above into your DLL project. Then move the symbol declarations from the headers listed above to the DLL header also making sure that they where declared with the correct qualifier listed below.

        __declspec(dlle xport)

        when compiling the DLL

        and

        __declspec(dlli mport)

        when compiling the program.



        Is that clearer?

        Comment

        • vermarajeev
          New Member
          • Aug 2006
          • 180

          #5
          Hi Banfa,
          That has worked. Now I'm able to compile my DLL project. It creates *.dll and *.lib files as you said.

          Now once that is done. What is the next step to proceed???

          As if now I have put myDll.dll ,myDll.ilk and myDll.lib into the same directory as the EXE of my first module(CMBEDIT as discussed in previous post). This is to test whether the DLL that I have created works with CMBEDIT module.

          But now the problem is how do I test it. Please let me know in steps..
          I'm eargly waiting for your reply.

          Thanx,

          Comment

          • Banfa
            Recognized Expert Expert
            • Feb 2006
            • 9067

            #6
            You need myDll.h as well

            If you have you EXE project and your DLL project as sub-projects of the same MSVC++ Workspace you can just make the EXE dependent on the DLL no need to copy files.

            Anyway what you do is

            #include myDll.h into your EXE source files
            Call functions from myDll in you EXE source files
            Include myDll.lib as one of the libraries used when linking the EXE

            EXE will then need to be able to find myDll.dll when it runs.

            Comment

            • vermarajeev
              New Member
              • Aug 2006
              • 180

              #7
              Hi Banfa,
              Thanks for all your help.

              I have linked my Dll with my module (CMBEDIT) but I'm still having some problems like some warnings and run time errors.

              First I would show you my class prototye which is as follows

              1)
              Code:
              //Header file ct.h
              CLass ConnectionTable
              {
                 private:
                        std::vector<CtRow*> table;
              };
              I get the following warning for the above declaration

              Code:
              d:\usr\TestDll\myDll\common\ct.h(431) : warning C4251: 'ConnectionTable::table' : class 'std::vector<_Ty>' needs to have dll-interface to be used by clients of class 'ConnectionTable'
              2) Also when I execute my module (CMBEDIT) I get the following run time error

              Code:
              "ENTRY POINT NOT DEFINED"
              "The procedure entry point?otherringnbr@atompair@@SAHAAVbasemolecule@@HHH@Z could not be located in the dynamic link library myDll.dll"
              Please help to correct these errors.
              Waiting for your reply

              Comment

              • Banfa
                Recognized Expert Expert
                • Feb 2006
                • 9067

                #8
                1. I refer you to the MS help documentation for C4251 (sorry the last time I created and used a DLL was before the time of C++).

                Error Message
                'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'


                To minimize the possibility of data corruption when exporting a class with __declspec(dlle xport), ensure that:

                All your static data is access through functions that are exported from the DLL.

                No inlined methods of your class can modify static data.

                No inlined methods of your class use CRT functions or other library functions use static data (see http://support.microso ft.com/default.aspx?sc id=KB;EN-US;190799 for more information).

                No methods of your class (regardless of inlining) can use types where the instantiation in the EXE and DLL have static data differences.

                You can avoid exporting classes by defining a DLL that defines a class with virtual functions, and functions you can call to instantiate and delete objects of the type. You can then just call virtual functions on the type.

                For more information on exporting templates, see http://support.microso ft.com/default.aspx?sc id=KB;EN-US;168958.

                C4251 can be ignored in Microsoft Visual C++ 2005 if you are deriving from a type in the Standard C++ Library, compiling a debug release (/MTd) and where the compiler error message refers to _Container_base .

                Copy Code
                // C4251.cpp
                // compile with: /EHsc /MTd /W2
                #include <vector>
                using namespace std;
                class Node;
                class __declspec(dlli mport) VecWrapper : vector<Node *> {}; // C4251

                Comment

                • Banfa
                  Recognized Expert Expert
                  • Feb 2006
                  • 9067

                  #9
                  2. A little strange, you will have to try and work out what actual symbol that error message refers to in your source code. However if it linked then it should run unless you are accidentally running with an older version of the DLL than the LIB you linked with. Check for old versions of the DLL lying around.

                  Comment

                  • vermarajeev
                    New Member
                    • Aug 2006
                    • 180

                    #10
                    Originally posted by Banfa
                    .
                    Hi Banfa,
                    Sorry for the delay, I was on leave yesterday.
                    Talking about the two problems that I have posted before, I'm more worried about the second error which says

                    Code:
                    "ENTRY POINT NOT DEFINED"
                    "The procedure entry point?otherringnbr@atompair@@SAHAAVbasemolecule@@H  HH@Z could not be located in the dynamic link library myDll.dll"
                    This is because I first need to get my module up and running and then later can think about the warnings.

                    Then I went through the code to refer otherringnbr@at ompair, the prototype of this class looks like this

                    Code:
                    #include "../myDll.h"
                    
                    class  basemolecule;
                    #define ap atompair::apinstance
                    
                    class MYDLL_API atompair
                    {
                    public:
                    
                    static atompair apinstance;
                    
                    static int allringsthesame(basemolecule& mol,int x,int y);
                    static int allsaturatedcarbonsbetween(basemolecule&,int x,int y);
                    static int anothercommonring(basemolecule&,int ring1,int x,int y);
                    static int aziridineformationpossible(basemolecule& mol,int x,int y);
                    static int bondbalance(basemolecule& mol,rownumber x,rownumber y);
                    static int otherringnbr(basemolecule& mol,int ringnum,int x,int y);
                    };
                    So you can now see static int otherringnbr(ba semolecule& mol,int ringnum,int x,int y);, which is where the error occurs as per error message which is like this
                    "ENTRY POINT NOT DEFINED"
                    "The procedure entry point?otherring nbr@atompair@@S AHAAVbasemolecu le@@H HH@Z could not be located in the dynamic link library myDll.dll"


                    As per your previous posts which says
                    All your static data is access through functions that are exported from the DLL.

                    Let me be frank, I'm really confused about what to do next, The above statement says I need to access static data through functions. But as you can see from the prototype of my class above there are lots of static members used.
                    Can you take the example of static int otherringnbr(ba semolecule& mol,int ringnum,int x,int y); and tell me what is that I need to do.

                    I'll be thankful to you
                    Thankx

                    Comment

                    • vermarajeev
                      New Member
                      • Aug 2006
                      • 180

                      #11
                      Hi Banfa,
                      I got rid of warnings by following this link

                      http://www.unknownroad .com/rtfm/VisualStudio/warningC4251.ht ml

                      But still I'm not able to solve this error
                      "ENTRY POINT NOT DEFINED"
                      "The procedure entry point?otherring nbr@atompair@@S AHAAVbasemolecu le@@H HH@Z could not be located in the dynamic link library myDll.dll"


                      Any help please
                      Thankx

                      Comment

                      • Banfa
                        Recognized Expert Expert
                        • Feb 2006
                        • 9067

                        #12
                        Hmmmm, can you access the other functions of the class OK ???

                        static int allringsthesame (basemolecule& mol,int x,int y);
                        static int allsaturatedcar bonsbetween(bas emolecule&,int x,int y);
                        static int anothercommonri ng(basemolecule &,int ring1,int x,int y);
                        static int aziridineformat ionpossible(bas emolecule& mol,int x,int y);
                        static int bondbalance(bas emolecule& mol,rownumber x,rownumber y);

                        If so then I would have a careful look for differences in how and where they are declared.

                        If it's a simple case that you are calling otherringnbr in the exe and getting this error then

                        1. Make sure that you can call otherringnbr in the DLL and it will link (temporarily stuff a call to otherringnbr into the constructor).

                        2. If that's OK it has to be how you have declared the function, it does not have the correct modifiers so is not being mangled in the correct way to found in myDLL.lib

                        Seeing more of the source code may help (particularly the headers)

                        It could be something as simple as not having the right headers included at the place you are making the function call

                        Comment

                        • vermarajeev
                          New Member
                          • Aug 2006
                          • 180

                          #13
                          Hi Banfa,
                          Thankx for your reply,

                          First of all let me make one thing clear that in the class prototype as given below

                          Code:
                          class  [B]basemolecule[/B];
                          #define ap atompair::apinstance
                          
                          class MYDLL_API atompair
                          {
                          public:
                          
                          static atompair apinstance;
                          
                          static int allringsthesame([B]basemolecule[/B]& mol,int x,int y);
                          static int allsaturatedcarbonsbetween([B]basemolecule[/B]&,int x,int y);
                          static int anothercommonring([B]basemolecule[/B]&,int ring1,int x,int y);
                          static int aziridineformationpossible([B]basemolecule[/B]& mol,int x,int y);
                          static int bondbalance([B]basemolecule[/B]& mol,rownumber x,rownumber y);
                          static int otherringnbr([B]basemolecule[/B]& mol,int ringnum,int x,int y);
                          static int otherringnbr([B]basemolecule[/B]& mol,int ringnum,int x,int y, int z);
                          };
                          basemolecule is a different class which is defined in basemolecule.h. Also I tried giving something like this
                          Code:
                          class  MYDLL_API basemolecule;
                          But that too didnt help me.

                          Also otherringnbr is an overloaded function with the following definations
                          defined in atompair.cpp
                          Code:
                          int atompair::otherringnbr(basemolecule& mol,int ringnum,int j,int z)
                          {
                              //some logic
                          }
                          
                          int atompair::otherringnbr(basemolecule& mol,int ringnum,int j,int z,int u)
                          {
                             //some logic
                          }
                          Finally these two static functions are being called in both, module ( CMBEDIT ) as well as in myDll project. I can just show you an example to have a picture of this by following

                          a) Called in CMBEDIT module in ncoord.cpp file
                          as like this
                          Code:
                          int anbr = ap.otherringnbr(mol, ringnum, a, b);
                          b) Also called in myDll project in many files like
                          1) atominring.cpp
                          2) atompair.cpp
                          3) ring.cpp etc etc (NOTE: 1,2,3 files are included in myDll)
                          and is called like this
                          Code:
                          a1 = ap.otherringnbr(mol,ring1,x,j);
                            a2 = ap.otherringnbr(mol,ring1,j,x);
                          Hope I'm not confusing you. If you are unable to understand me please feel free to ask. I'm trying my best to make you get the picture of what is happening

                          Waiting for a reply eagerly

                          Comment

                          • vermarajeev
                            New Member
                            • Aug 2006
                            • 180

                            #14
                            Hi Banfa,
                            Thankx, I have fixed that problem and is glad to see the output. Actually It was a silly mistake made by me. I had not copied the modified DLL in my executable directory hence was getting that error.
                            But this wouldnt have been possible without your help. I'm glad :))

                            Thankx Banfa, I'll be back if any problem. You are awesome.

                            Comment

                            • vermarajeev
                              New Member
                              • Aug 2006
                              • 180

                              #15
                              Hi Banfa,
                              Thankx for all the support that you have provided tiil now...

                              Now I'm facing a different kind of problem...
                              The problem is

                              My class looks something like this

                              Defined in myDll.dll
                              Code:
                              class ConnectionTable
                              {
                                private: 
                                     std::string _info;
                              };
                              I get the following warning for above like
                              warning C4251: 'ConnectionTabl e::_info' : class 'std::basic_str ing<_Elem,_Trai ts,_Ax>' needs to have dll-interface to be used by clients of class 'ConnectionTabl e'

                              Also when I run the above dll with my *.exe in debug mode I get runtime error.
                              This runtime error is related to xstring...

                              Now my question is if I'm calling _info(defined in myDll.dll) in my *.exe, Is it that the runtime error whatever I'm getting is due to calling of _info(defined in myDll.dll) in *.exe..

                              What my guess at this moment is that according to the warning given above, clients of class 'ConnectionTabl e' which is I guess *.exe requires to have dll-interface but it is unable to find the dll-interface, and the runtime error is happening because of that...

                              This is because when I use QString( a string defined in QT(GUI tool)), this works fine for me. But I'm in need to use std::string in my code.

                              I'm finally stuck here and needs your help ASAP.

                              I can show the sample code for your clear understading

                              Defined in myDll.dll
                              Code:
                              class ConnectionTable
                              {
                                public:
                                      std::string info()
                                       {
                                          return _info;
                                       }
                                private: 
                                     std::string _info;
                              };
                              Defined in myexe.exe
                              Code:
                              class myClass
                              {
                                public: 
                                      void someFunction();
                                private:
                                      ConnectionTable* ct;
                              };
                              
                              void myClass::someFunction()
                              {
                                  std::string str = ct->info();
                                  QString s = QString(str.data());  //this is Qt related code
                                  //Pass this QString s to functions which use Qt libraries
                              }
                              NOTE: the above example is just a sample code to give you a picture of what is happening.

                              Thanks for your understanding.. .

                              Comment

                              Working...