I have this template smart pointer class in a dll.
sp.h
---------
#ifdef VLIB_EXPORTS
#define VLIB_API __declspec(dllexport)
#else
#define VLIB_API __declspec(dllimport)
#endif
template < typename T > class VLIB_API SP
{
protected:
T* m_pData;
long* m_pRefCounter;
public:
SP(void);
{
m_pData = NULL;
m_pRefCounter = NULL;
}
...
...
};
ImagePtr.h
---------------
class VLIB_API CVImagePtr
{
....
}
MainLib.h
-------------
#include sp.h
#include ImagePtr.h
typedef SP<CVBlob> CVBlobPtr;
class VLIB_API CVLib
{
public:
virtual CVBlobPtr CreateBlob() = 0;
virtual CVImagePtr CreateImg() = 0;
};
When I try to use this class in another project (CVMLib), the compiler will complain this:
error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall SP::~SP(void)"
but no problem for CVImagePtr.
class VMLIB_API CVMLib : public CVLib
{
public:
virtual CVBlobPtr CreateBlob();
virtual CVImagePtr CreateImg();
};
It seems there's a problem when the class is a template. If so, how do I export a template class?
Can somebody help me resolve this? Thank you!
As suspected, I'm not exporting the template class properly. This is what I did:
MainLib.h
#include sp.h
#include ImagePtr.h
#ifdef VLIB_EXPORTS
#define VLIB_API __declspec(dllexport)
#define EXPIMP_TEMPLATE
#else
#define VLIB_API __declspec(dllimport)
#define EXPIMP_TEMPLATE extern
#endif
EXPIMP_TEMPLATE template class VLIB_API SP<CVBlob>;
typedef SP<CVBlob> CVBlobPtr;
class VLIB_API CVLib
{
public:
virtual CVBlobPtr CreateBlob() = 0;
virtual CVImagePtr CreateImg() = 0;
};
You can find more information here:
http://support.microsoft.com/kb/168958
You need to mark the class with extern "C" in order to have the non mangled name on the implementation of the class as well as the header.
Have a look at this canonical answer as to why.
Related
I'm programing in visual studio c++. I have Field, IField, Map and IMap in DLL. I create interfaces IField and IMap to have access to Field and Map in unit test. When i run this simple code in unit test:
IMap m;
IField f(3, 4);
m.shoot(f);
I have following error:
LNK2019 unresolved external symbol "public: virtual __thiscall
Field::~Field(void)" (??1Field##UAE#XZ) referenced in function
"public: virtual void * __thiscall Field::`scalar deleting
destructor'(unsigned int)" (??_GField##UAEPAXI#Z) TestShipGameDll
#pragma once
class Field
{
public:
Field(int x, int y) : x(x), y(y) {}
virtual ~Field() {}
protected:
int x;
int y;
};
.
#ifdef IFIELD_EXPORTS
#define IFIELD_API __declspec(dllexport)
#else
#define IFIELD_API __declspec(dllimport)
#endif
class IField :
public Field
{
public:
IFIELD_API IField(int x, int y) :Field(x, y)
IFIELD_API virtual ~IField() {}
};
.
class Map
{
public:
Map();
virtual ~Map();
void shoot(Field field)
{
//here is empty body of function
}
};
.
#ifdef IMAP_EXPORTS
#define IMAP_API __declspec(dllexport)
#else
#define IMAP_API __declspec(dllimport)
#endif
class IMap :
public Map
{
public:
IMAP_API IMap() {}
IMAP_API virtual ~IMap() {}
IMAP_API void shoot(Field field)
{
Map::shoot(field);
}
};
.
It's weird. It looks like it was missing copying constructor but I do not have any pointers in Field. Only automatic variables x and y. Do you have any tips to resolve this fancy error?
You have to export the whole class with IFIELD_API - otherwise the compiler-generated functions are not visible outside the shared library and you will get linker errors.
I've got a problem using 3rd party .dll library:
That library has some class with methods I need to use in my compiled .dll via JNI from my Java app.
I'm trying to declare something like that :
#ifdef SERVER_EXPORTS
#define SERVER_API __declspec(dllexport)
#else
#define SERVER_API __declspec(dllimport)
#endif
namespace MYDLLNAMESPACE
{
class SERVER_API IServer
{
public:
int NFun(int func);
};
class SERVER_API ServerClass : public IServer {
public:
ServerClass();
int NFun(int func) {
return MYDLLNAMESPACE::ServerClass::NFun(func);
}
};
}
Ant then use it in code like :
IServer *Myserv = new Server();
int a = Myserv->NFun(5007);
return a;
but it goes to the error "error LNK2019: unresolved external symbol "__declspec(dllimport) public: int __thiscall MYDLLNAMESPACE::IServer:"
I need to do something like:
Iserver myServer = new Server();
int result = myServer.do_smth();
return result;
where Server is MYDLL.dll --> namespace MYDLLNAMESPACE --> class Server
Is there any ways how to do it?
P.S. I haven't any .lib of .h files of 3rd party .dll
EDIT:
Now I've got Server.h file :
namespace NS {
class __declspec(dllexport) ServerClass
{
public:
ServerClass() {
}
const char* GParam(const char* key);
const char* SParam(const char* key, const char* value);
};
}
And my Impl.cpp file, where I tryin' to instantiate ServerClass and use its method 'GParam' like this:
ServerClass *serv = new ServerClass();
const char* str = serv->GParam("LastErrorTxt");
but it goes to StackOverFlowException, seems like serv->GParam("LastErrorTxt") is executing itself instead of dll class implementation
Problem is solved by using com4j:
http://com4j.kohsuke.org/
I have an DLL in which I have added a second class which has only static members, but when I try to build this I got linker error:
Error 14 error LNK2001: unresolved external symbol "__declspec(dllimport) private: static double BubblyCore::BubblyTime::delta" (__imp_?delta#BubblyTime#BubblyCore##0NA) D:\Projekty\bubbly-engine\BCore\BCore.obj BCore
And same for second member.
Here is my header:
#ifdef BCOREDLL_EXPORTS
#define BCOREDLL_API __declspec(dllexport)
#else
#define BCOREDLL_API __declspec(dllimport)
#endif
#include <..\BDisplay.h>
#include <ctime>
#include <chrono>
typedef std::chrono::time_point<std::chrono::system_clock, std::chrono::system_clock::duration> BChronoTime;
namespace BubblyCore
{
// This class is exported from the BCOREDll.dll
class BCOREDLL_API MainBubble
{
public:
private:
BDisplay* pbDisplay;
bool isRunning;
public:
MainBubble(BDisplay* pbDisplay);
void Start();
void Stop();
private:
void Run();
void Render();
void CleanUp();
};
class BCOREDLL_API BubblyTime
{
public:
static BChronoTime bStartTime;
private:
static double delta;
public:
static long getTime();
static double getDelta();
static void setDelta(double sDelta);
};
}
I am talking specific about BubblyTime. The first one is Ok so far.
Inside one of your .cpp files, add the following lines :
double BubblyCore::BubblyTime::delta = 0.0;
Declaring static variables in a header file won't be sufficient. You need to declare their real instances in some .cpp files.
I have an application code which invokes a DLL lib with explicit linkage (or run time linking) for accessing an exported class.
DLL.h
#ifdef DLL_EXPORT
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
FooDLL.h
#include "DLL.h"
class DLL_API Foo
{
public:
void doSomeThing();
};
extern "C" DLL_API Foo* _getInstance() {
return new Foo();
}
typedef Foo* (*getInstanceFactory)();
Foo* getInstance() {
HINSTANCE dllHandle = LoadLibraryA("Foo.dll");
getInstanceFactory factory_func = (getInstanceFactory)GetProcAddress(dllHandle, "_getInstance");
return factory_func();
}
FooDLL.cpp
#include "FooDLL.h"
Foo::doSomething() {
// .......
}
Application.cpp (which invokes DLL)
#include "FooDLL.h"
Foo* obj = getInstance();
obj->doSomething(); // XXX this line can be compiled and linked only when DLL is already in path
The above code can be built (e.g. compiled&linked) only when the DLL file is included in lib path. Otherwise I got unresolved external symbol error.
error LNK2001: unresolved external symbol "__declspec(dllimport) public: void __thiscall Foo::doSomething()" .....
Is it possible to build the application code with only DLL header file (i.e. FooDLL.h) and without DLL/LIB files during the build time? (p.s. The class implementation must be in cpp file.)
thanks!
with virtual function.
class Foo
{
public:
void virtual doSomeThing();
};
Yes it is possible. If you did not export a class you would not need a header file at all.
I am not sure why you placed call to LoadLibrary in the header file.
Since you are exporting class, you have to let the compiler know the type. Besides, you do not have to export entire class, you can export only specific member functions of the class you want to expose
Your dll header to be used in a dll and exe projects, should include following (I used my own names):
#ifdef WIN32DLL_EXPORTS
#define WIN32DLL_API __declspec(dllexport)
#else
#define WIN32DLL_API __declspec(dllimport)
#endif
class CWin32DLL
{
public:
CWin32DLL();
int WIN32DLL_API GetInt();
};
Implementation:
#include "stdafx.h"
#include "Win32DLL.h"
extern "C" WIN32DLL_API CWin32DLL* _getInstance()
{
return new CWin32DLL();
}
// This is the constructor of a class that has been exported.
// see Win32DLL.h for the class definition
CWin32DLL::CWin32DLL()
{
}
int CWin32DLL::GetInt()
{
return 42;
}
Your DLL consumer:
#include "Win32DLL.h"
#include "SomeOther.h"
typedef CWin32DLL* (*getInstanceFactory)();
HINSTANCE dllHandle = LoadLibrary(_T("Win32DLL.dll"));
getInstanceFactory factory_func = (getInstanceFactory)GetProcAddress(dllHandle, "_getInstance");
CWin32DLL* pWin32 = factory_func();
int iRet = pWin32->GetInt();
Do not forget to define WIN32DLL_EXPORTS (or equivalent) in project properties, C++, Preprocessor, Preprocessor Definitions for the dll.
I can't quite figure out where there is a mistake. I am creating a DLL and then using it in a C++ console program (Windows 7, VS2008). But I get LNK2019 unresolved external symbol when trying to use the DLL functions.
First the export:
#ifndef __MyFuncWin32Header_h
#define __MyFuncWin32Header_h
#ifdef MyFuncLib_EXPORTS
# define MyFuncLib_EXPORT __declspec(dllexport)
# else
# define MyFuncLib_EXPORT __declspec(dllimport)
# endif
#endif
This is one header file I then use in:
#ifndef __cfd_MyFuncLibInterface_h__
#define __cfd_MyFuncLibInterface_h__
#include "MyFuncWin32Header.h"
#include ... //some other imports here
class MyFuncLib_EXPORT MyFuncLibInterface {
public:
MyFuncLibInterface();
~MyFuncLibInterface();
void myFunc(std::string param);
};
#endif
Then there is the dllimport in the console program, which has the DLL included in the Linker->General->Additional Library Directories:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
__declspec( dllimport ) void myFunc(std::string param);
int main(int argc, const char* argv[])
{
std::string inputPar = "bla";
myFunc(inputPar); //this line produces the linker error
}
I can't figure out what's going wrong here; it must be something really simple and fundamental.
You're exporting a class member function void MyFuncLibInterface::myFunc(std::string param); but trying to import a free function void myFunc(std::string param);
Make sure you #define MyFuncLib_EXPORTS in the DLL project. Make sure you #include "MyFuncLibInterface.h" in the console app without defining MyFuncLib_EXPORTS.
The DLL project will see:
class __declspec(dllexport) MyFuncLibInterface {
...
}:
And the console project will see:
class __declspec(dllimport) MyFuncLibInterface {
...
}:
This allows your console project to use the class from the dll.
EDIT: In response to comment
#ifndef FooH
#define FooH
#ifdef BUILDING_THE_DLL
#define EXPORTED __declspec(dllexport)
#else
#define EXPORTED __declspec(dllimport)
#endif
class EXPORTED Foo {
public:
void bar();
};
#endif
In the project which actually implements Foo::bar() BUILDING_THE_DLL must be defined. In the project which tries to use Foo, BUILDING_THE_DLL should not be defined. Both projects must #include "Foo.h", but only the DLL project should contain "Foo.cpp"
When you then build the DLL, the class Foo and all its members are marked as "exported from this DLL". When you build any other project, the class Foo and all its members are marked as "imported from a DLL"
You need to import the class not a function. After that, you can call the class member.
class __declspec( dllimport ) MyFuncLibInterface {
public:
MyFuncLibInterface();
~MyFuncLibInterface();
void myFunc(std::string param);
};
int main(int argc, const char* argv[])
{
std::string inputPar = "bla";
MyFuncLibInterface intf;
intf.myFunc(inputPar); //this line produces the linker error
}