static member in DLL

Hello,
For a project I need to handle numbers that only have a predefined range of values [0, max) (not known at compile time) and after reaching the end, wrap to 0, i.e. max == 0, max + 1 == 1, etc.

The project is organized in a way that there is the main executable (a) that loads dynamically 2 dlls (b, c).

Since "c" handles most of the arithmetics, I defined the class in "c".
But the numbers are used all over the project (in a, b and c).

I implemented the modulus (= max) as a static protected member of the class to ensure the same modulus for all numbers (there is no use in adding/comparing/.. numbers based on separate moduli).

Right now I define the static member in c.cpp.

In Visual Studio I receive an error "error LNK2001: not resolved external symbol <my static member variable>".
This error is shown only in "a" and "b", not in "c" ("c" compiles without errors)

This looks to me as if it's not accessible in "a" and "b".
btw: I have not mentioned it in "c"s def file.

I include the Headerfile "c.h" in "a" and "b".


What can I do?


c.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
ifndef myPosType_h
#define myPosType_h

#include <cassert>
#include <limits>
#include "myLogger.h"

class MyPosBaseType 
{
public:
  typedef long long baseType;

  static void setModulo(const baseType modulo)
  {
    modulo_ = modulo;
  }

protected:
  static baseType modulo_;
};

class MyPosDiffType : public MyPosBaseType
{
  // operations such as adding, comparing, constructors etc.
  // used for position differences
};

class MyPosType : public MyPosBaseType
{
  // operations such as adding, comparing, constructors etc.
  // used for positions
};


#endif 


c.cpp:
1
2
3
4
#include "stdafx.h"
#include "myPosType.h"

MyPosBaseType::baseType MyPosBaseType::modulo_ (8192000);
You don't appear to have exported your class.
Thank you for the advice.
I found a site that suggested using this form
 
class __declspec(dllexport) AClassName {/*...*/};

to export a class in a dll.

I did this with all 3 required classes and also added the classes to the def-file.

No I get an error LNK2001: not resolved external symbol "<class name>" for all 3 classes when compiling the dll.
I also get an error LNK1120: 3 not resolved external references.

I also read that I have to use __declspec(dllimport) in the other modules but I thought that at least this one should now compile and link.
I found a solution (at least it compiles and links fine):
* insert __declspec(dllexport) before the class names
* don't define any methods in the header file. Put them all in the cpp file.
* don't enter the classes in the def file

I found this here:
http://home.hiwaay.net/~georgech/WhitePapers/Exporting/Exp.htm
closed account (S6k9GNh0)
Common method is also defining a macro like so: #define EXPORT __declspec(dllexport) and vice versa for import.
You need to use a macro because you need to export it when it's being built, but imported when used.
Is EXPORT defined automatically when I'm producing a DLL or do I need to #define it myself?

I would do it this way:

export_c.h (used in the DLL "c"):
1
2
3
4
5
#ifndef export_c_h
#define export_c_h
#define EXPORT __declspec(dllexport)
#include "c.h"
#endif 



modification of c.h (used in "a" and "b"):
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef myPosType_h
#define myPosType_h
#ifndef EXPORT
#define EXPORT __declspec(dllimport)
#endif

class EXPORT MyPosBaseType 
{ /* ...*/}

/*...*/

#endif


and use this in the DLL?

The other functions are exported via the .def-file so they don't need special handling.
Don't bother with DEF files. They're almost impossible to maintain with C++.
I just found out that the EXPORT macro is defined in a header afxv_w32.h which is indirectly included.

But it's also set in the module "b" (which is also a dll) but there it should not be set since this module just imports the class.

So I think I have to use seperate headers for the module itself and for export anyway.

internal_c.h (used in the DLL "c"):
1
2
3
4
5
#ifndef internal_c_h
#define internal_c_h
#define EXPORT_C_H
#include "c.h"
#endif  




modification of c.h (used in "a" and "b"):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef myPosType_h
#define myPosType_h
#ifdef EXPORT_C_H
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif

class DLLEXPORT MyPosBaseType 
{ /* ...*/}

/*...*/

#endif 

That's what you need.

You'll find that if you create a DLL project Calculator, VS will define a macro CALCULATOR_EXPORTS that you can use to drive the switch.
Topic archived. No new replies allowed.