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/
Related
I have a Visual Studio C++ project containing main program and a DLL module.
The DLL has a class with the following definition:
// .h
#ifdef _USRDLL
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#endif
class DLLAPI EClass
{
public:
static int value;
static int get_value();
};
// .cpp
int EClass::value = 1;
int EClass::get_value()
{
return value;
}
The DLL project is compiled successfully, both symbols (value and get_value) are observable by Dependency Walker.
In the main program, I can call the static function get_value
int v = EClass::get_value(); // Ok, v = 1
but when I try to access the field value directly
int v = EClass::value; // Error
I get an error
LNK2001 unresolved external symbol "public: static int EClass::value" (?value#EClass##2HA)
It is possible to avoid using accessors for static fields?
The macro _USRDLL should be defined only in the DLL project.
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.
IClass (My interface):
#ifndef _ICLASS_H
#define _ICLASS_H
#include <sstream>
namespace Test
{
class __declspec(dllexport) IClass
{
public:
virtual ~IClass() {}
virtual bool Init(const std::string &path) = 0;
};
}
#endif
Class.h
#ifndef _CLASS_H
#define _CLASS_H
#include "IClass.h"
#include <memory>
#include <sstream>
#include <stdio.h>
namespace Test
{
class Class: public IClass
{
public:
Class();
~Class();
bool Init(const std::string &path);
};
}
#endif
Class.cpp
#include "Class.h"
namespace Test
{
Class::Class()
{
}
bool Class::Init(const std::string &path)
{
try
{
// do stuff
return true;
}
catch(std::exception &exp)
{
return false;
}
}
}
main (in exe, dll linked implicitly)
#include "IClass.h"
using namespace Test;
int main(int argc, char* argv[])
{
std::shared_ptr<IClass> test = std::make_shared<Class>(); // error: unreferenced Class
test->Init(std::string("C:\\Temp"));
}
At the moment Class is not declared
-> if I include Class.h to main following error occurs: LNK2019: unresolved external symbol: add class __declspec(dllexport) Class : public IClass resolve this linker issue, but is it ok to do it this way?
-> I also can't do this: std::shared_ptr<IClass> test = std::make_shared<IClass>();
(because it's not allowed to create an object of abstract class)
How can I solve this issue and is this best practise?
If you want your EXE to allocate a new "Class" object, the EXE code has to know the Class type. If you want to keep the Class type unknown from the EXE, one solution may be to export from your DLL a factory function, which will construct a Class object and return it as an IClass pointer.
See How to implement the factory pattern in C++ correctly
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.
My code is stored in a main.cpp file which contains the void main() function, and a class MyClass which I now want to split to another file. IDE is Microsoft Visual Studio 2008 Professional.
myclass.h
#include <tchar.h>
class MyClass {
public:
static bool MyFunction (TCHAR* someStringArgument);
};
myclass.cpp
#include <tchar.h>
class MyClass {
private:
static bool someProperty;
static void doSomeOneTimeCode () {
if (!someProperty) {
/* do something */
someProperty = true;
}
}
public:
static bool MyFunction (TCHAR* someStringArgument) {
doSomeOneTimeCode();
/* do something */
return true;
}
};
bool MyClass::someProperty = false;
main.cpp
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include "myclass.h"
void main () {
if (MyClass::MyFunction(TEXT("myString"))) {
_tprintf(TEXT("Yay\n"));
}
}
However, when I try to run it, I get two linker errors.
LNK2019: unresolved external symbol ... (mentions MyClass::MyFunction)
LNK1120: 1 unresolved externals
What can I do to prevent these linker errors?
You declared two classes here. One of them is in myclass.h and the other is in myclass.cpp. Try the following instead:
myclass.h
#ifndef myclass_h_included
#define myclass_h_included
#include <tchar.h>
class MyClass {
private:
static bool someProperty;
static void doSomeOneTimeCode ();
public:
static bool MyFunction (TCHAR* someStringArgument);
};
#endif //!myclass_h_included
myclass.cpp
#include "myclass.h"
/*static*/ bool MyClass::someProperty = false;
void
MyClass::doSomeOneTimeCode() {
//...
}
bool
MyClass::MyFunction(TCHAR* someStringArgument) {
//...
}
Your main.cpp can stay the same. I would pay attention to UncleBens reply as well. One time initialization code should be hidden if at all possible.
Yo can't split a class definition in parts. It must be defined as a whole in one place. If you want to just have some methods of the class defined create a interface class that the MyClass class will later inherit. You should put the class' definition in a header file (myclass.h) and it's implementation in a cpp file (myclass.cpp). That way you can include the "myclass.h" in your main cpp file and use the class in your main function (which should be int main() or int main( int argc, char *argv[] )).
Strange that you didn't get a compiler error, as you are redefining MyClass.
Definitions (implementations) go into the cpp, and they are defined like this:
#include "myclass.h"
//helper functions, particularly if static, don't need to be in the class
//unnamed namespace means this stuff is available only for this source file
namespace
{
bool someProperty;
void doSomeOneTimeCode () {
if (!someProperty) {
/* do something */
someProperty = true;
}
}
}
bool MyClass::MyFunction (TCHAR* someStringArgument) {
doSomeOneTimeCode();
/* do something */
return true;
}