Making Visual C++ DLL from C++ class
I have the following C++ code to make dll (Visual Studio 2010).
class Shape {
public:
Shape() {
nshapes++;
}
virtual ~Shape() {
nshapes--;
};
double x, y;
void move(double dx, double dy);
virtual double area(void) = 0;
virtual double perimeter(void) = 0;
static int nshapes;
};
class __declspec(dllexport) Circle : public Shape {
private:
double radius;
public:
Circle(double r) : radius(r) { };
virtual double area(void);
virtual double perimeter(void);
};
class __declspec(dllexport) Square : public Shape {
private:
double width;
public:
Square(double w) : width(w) { };
virtual double area(void);
virtual double perimeter(void);
};
I have the __declspec,
class __declspec(dllexport) Circle
I could build a dll with the following command
CL.exe /c example.cxx
link.exe /OUT:"example.dll" /DLL example.obj
When I tried to use the library,
Square* square; square->area()
I got the error messages. What's wrong or missing?
example_unittest.obj : error LNK2001: unresolved external symbol "public: virtual double __thiscall ... Square::area(void)" (?area@Square@@UAENXZ)
ADDED
Following wengseng's answer, I modified the header file, and for DLL C++ code, I added
#define XYZLIBRARY_EXPORT
However, I still got errors.
SOLVED
For main program that links example.dll, I didn't link example.lib.
cl /MD /EHsc gtest_main.cc example_unittest.cc /I"./include" /link /libpath:"./lib" /libpath:"." gtest_md.lib example.lib /out:gtest_md_release.exe
With the addition, everythin开发者_如何学JAVAg works fine.
In DLL, i suggest to add a macro, and add XYZLIBRARY_EXPORT in pre-processor:
#if defined(XYZLIBRARY_EXPORT) // inside DLL
# define XYZAPI __declspec(dllexport)
#else // outside DLL
# define XYZAPI __declspec(dllimport)
#endif // XYZLIBRARY_EXPORT
class XYZAPI Circle
It will export the Circle class.
In EXE, import the Circle class, without adding pre-processor, as it will import the class by default.
Instead of exporting a C++ class directly in a DLL, you could expose a factory function which uses the C calling convention and avoid name mangling issues.
class Shape {
...
};
class Circle : public Shape {
...
};
extern "C" Circle* newCircle();
extern "C" void deleteCircle(Circle* p);
The DLL's user can then call newCircle() to create a Circle object, do whatever it needs to do with it and then call deleteCircle() on it to get rid of it. You can't just call delete on the returned pointer because the DLL may not be linking against the same instance of the C++ runtime library as the DLL's user.
You must export the Shape class to resolve "static int Shape::nshapes" error (and maybe the other errors as well).
Don't forget to link the library (example.lib) generated with the DLL
精彩评论