By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
446,413 Members | 996 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 446,413 IT Pros & Developers. It's quick & easy.

Creating DLLs

100+
P: 180
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.cpp

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...PLease 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.
Sep 28 '06 #1
Share this Question
Share on Google+
15 Replies


Banfa
Expert Mod 5K+
P: 8,916
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(dllexport)

when compiling the DLL

and

__declspec(dllimport)

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.
Sep 28 '06 #2

100+
P: 180
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(dllexport)

when compiling the DLL

and

__declspec(dllimport)

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

Expand|Select|Wrap|Line Numbers
  1. // myDll.cpp : Defines the entry point for the DLL application.
  2. //
  3.  
  4. #include "stdafx.h"
  5. #include "myDll.h"
  6. BOOL APIENTRY DllMain( HANDLE hModule, 
  7.                        DWORD  ul_reason_for_call, 
  8.                        LPVOID lpReserved
  9.                      )
  10. {
  11.     switch (ul_reason_for_call)
  12.     {
  13.     case DLL_PROCESS_ATTACH:
  14.     case DLL_THREAD_ATTACH:
  15.     case DLL_THREAD_DETACH:
  16.     case DLL_PROCESS_DETACH:
  17.         break;
  18.     }
  19.     return TRUE;
  20. }
  21.  
  22. // This is an example of an exported variable
  23. MYDLL_API int nmyDll=0;
  24.  
  25. // This is an example of an exported function.
  26. MYDLL_API int fnmyDll(void)
  27. {
  28.     return 42;
  29. }
  30.  
  31. // This is the constructor of a class that has been exported.
  32. // see myDll.h for the class definition
  33. CmyDll::CmyDll()
  34.     return; 
  35. }
Also I have included my common files here as
Expand|Select|Wrap|Line Numbers
  1. // stdafx.h : include file for standard system include files,
  2. // or project specific include files that are used frequently, but
  3. // are changed infrequently
  4. //
  5.  
  6. #pragma once
  7.  
  8.  
  9. #define WIN32_LEAN_AND_MEAN        // Exclude rarely-used stuff from Windows headers
  10. // Windows Header Files:
  11. #include <windows.h>
  12.  
  13.  
  14.  
  15. // TODO: reference additional headers your program requires here
  16. #include "common/ct.h"
  17. #include "common/route.h"
  18. #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....
Sep 28 '06 #3

Banfa
Expert Mod 5K+
P: 8,916
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.cpp

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(dllexport)

when compiling the DLL

and

__declspec(dllimport)

when compiling the program.



Is that clearer?
Sep 28 '06 #4

100+
P: 180
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,
Sep 29 '06 #5

Banfa
Expert Mod 5K+
P: 8,916
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.
Sep 29 '06 #6

100+
P: 180
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)
Expand|Select|Wrap|Line Numbers
  1. //Header file ct.h
  2. CLass ConnectionTable
  3. {
  4.    private:
  5.           std::vector<CtRow*> table;
  6. };
I get the following warning for the above declaration

Expand|Select|Wrap|Line Numbers
  1. 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

Expand|Select|Wrap|Line Numbers
  1. "ENTRY POINT NOT DEFINED"
  2. "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
Sep 30 '06 #7

Banfa
Expert Mod 5K+
P: 8,916
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(dllexport), 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.microsoft.com/default.aspx?scid=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.microsoft.com/default.aspx?scid=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(dllimport) VecWrapper : vector<Node *> {}; // C4251
Sep 30 '06 #8

Banfa
Expert Mod 5K+
P: 8,916
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.
Sep 30 '06 #9

100+
P: 180
.
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

Expand|Select|Wrap|Line Numbers
  1. "ENTRY POINT NOT DEFINED"
  2. "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@atompair, the prototype of this class looks like this

Expand|Select|Wrap|Line Numbers
  1. #include "../myDll.h"
  2.  
  3. class  basemolecule;
  4. #define ap atompair::apinstance
  5.  
  6. class MYDLL_API atompair
  7. {
  8. public:
  9.  
  10. static atompair apinstance;
  11.  
  12. static int allringsthesame(basemolecule& mol,int x,int y);
  13. static int allsaturatedcarbonsbetween(basemolecule&,int x,int y);
  14. static int anothercommonring(basemolecule&,int ring1,int x,int y);
  15. static int aziridineformationpossible(basemolecule& mol,int x,int y);
  16. static int bondbalance(basemolecule& mol,rownumber x,rownumber y);
  17. static int otherringnbr(basemolecule& mol,int ringnum,int x,int y);
  18. };
So you can now see static int otherringnbr(basemolecule& 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?otherringnbr@atompair@@SAHAAVbasemolecule@@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(basemolecule& mol,int ringnum,int x,int y); and tell me what is that I need to do.

I'll be thankful to you
Thankx
Oct 3 '06 #10

100+
P: 180
Hi Banfa,
I got rid of warnings by following this link

http://www.unknownroad.com/rtfm/VisualStudio/warningC4251.html

But still I'm not able to solve this error
"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"


Any help please
Thankx
Oct 3 '06 #11

Banfa
Expert Mod 5K+
P: 8,916
Hmmmm, can you access the other functions of the class OK ???

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);

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
Oct 3 '06 #12

100+
P: 180
Hi Banfa,
Thankx for your reply,

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

Expand|Select|Wrap|Line Numbers
  1. class  basemolecule;
  2. #define ap atompair::apinstance
  3.  
  4. class MYDLL_API atompair
  5. {
  6. public:
  7.  
  8. static atompair apinstance;
  9.  
  10. static int allringsthesame(basemolecule& mol,int x,int y);
  11. static int allsaturatedcarbonsbetween(basemolecule&,int x,int y);
  12. static int anothercommonring(basemolecule&,int ring1,int x,int y);
  13. static int aziridineformationpossible(basemolecule& mol,int x,int y);
  14. static int bondbalance(basemolecule& mol,rownumber x,rownumber y);
  15. static int otherringnbr(basemolecule& mol,int ringnum,int x,int y);
  16. static int otherringnbr(basemolecule& mol,int ringnum,int x,int y, int z);
  17. };
basemolecule is a different class which is defined in basemolecule.h. Also I tried giving something like this
Expand|Select|Wrap|Line Numbers
  1. class  MYDLL_API basemolecule;
But that too didnt help me.

Also otherringnbr is an overloaded function with the following definations
defined in atompair.cpp
Expand|Select|Wrap|Line Numbers
  1. int atompair::otherringnbr(basemolecule& mol,int ringnum,int j,int z)
  2. {
  3.     //some logic
  4. }
  5.  
  6. int atompair::otherringnbr(basemolecule& mol,int ringnum,int j,int z,int u)
  7. {
  8.    //some logic
  9. }
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
Expand|Select|Wrap|Line Numbers
  1. 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
Expand|Select|Wrap|Line Numbers
  1. a1 = ap.otherringnbr(mol,ring1,x,j);
  2.   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
Oct 3 '06 #13

100+
P: 180
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.
Oct 5 '06 #14

100+
P: 180
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
Expand|Select|Wrap|Line Numbers
  1. class ConnectionTable
  2. {
  3.   private: 
  4.        std::string _info;
  5. };
I get the following warning for above like
warning C4251: 'ConnectionTable::_info' : class 'std::basic_string<_Elem,_Traits,_Ax>' needs to have dll-interface to be used by clients of class 'ConnectionTable'

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 'ConnectionTable' 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
Expand|Select|Wrap|Line Numbers
  1. class ConnectionTable
  2. {
  3.   public:
  4.         std::string info()
  5.          {
  6.             return _info;
  7.          }
  8.   private: 
  9.        std::string _info;
  10. };
Defined in myexe.exe
Expand|Select|Wrap|Line Numbers
  1. class myClass
  2. {
  3.   public: 
  4.         void someFunction();
  5.   private:
  6.         ConnectionTable* ct;
  7. };
  8.  
  9. void myClass::someFunction()
  10. {
  11.     std::string str = ct->info();
  12.     QString s = QString(str.data());  //this is Qt related code
  13.     //Pass this QString s to functions which use Qt libraries
  14. }
NOTE: the above example is just a sample code to give you a picture of what is happening.

Thanks for your understanding...
Oct 26 '06 #15

Banfa
Expert Mod 5K+
P: 8,916
I think that your guess is a good one.

Since std::string does not have a dll interface when you try to use it inside a dll from your exe the program is unable to perform the correct action.

std::string.data() is not declared dll_export.

I think you will have to write your code in a way that does not try to pass standard classes between exe and dll.

DLL based classes and functions should only return Basic Types and other DLL based classes and functions.

ConnectionTable::info could return char * from which you can reconstruct the string

std::string str = ConnectionTable::info();

still works.
Oct 26 '06 #16

Post your reply

Sign in to post your reply or Sign up for a free account.