There is shared class. Declarator is in shared header, implementation is in main program. Main program load DLL and exec some function from it, function create object of shared class.
Test code:
shared_header.h:
#include<stdio.h>
class sharedClass{
public:
sharedClass();
};
plugin.cpp -> libplugin.dll
#include"shared_header.h"
extern "C"
void loader(){
printf("Plugin is loaded!\n");
new sharedClass;
}
base.cpp -> base.exe
#include"shared_header.h"
sharedClass::sharedClass(){
printf("Shared class is loaded!\n");
}
int main(){
/*
some actions to load libplugin.dll and exec function loader
*/
return 0;}
So, I want see
Plugin is loaded!
Shared class is loaded!
And it works on Linux. But while I link libplugin.dll on Windows I have error "undefined refernce to sharedClass::sharedClass()". How I need link program and plugin to use this way?
PS. Mingw, stable version.
PPS. I'm so sorry for my terrible English.
Windows DLLs are non exactly the same thing as UNIX/Linux shared objects.
On Windows, DLLs must be fully linked and have all their references defined. Therefore, as your file plugin.cpp references the sharedClass constructor, the linker will require that this constructor is defined and available to create the DLL. It is not possible to provide it in the executable that loads the DLL.
On UNIX/Linux, shared objects behave differently. Their dependencies are solved when they are loaded by the executable. Therefore, the executable can provide some of the functions needed by the shared object.
Related
I'm not really sure if that is the actual name of what I mean, but you'll get it.
Supose I have 3 projects, 2 of them builds as libraries, and the other one as an executable. For my scenario I'll use MSVC++ and the libraries will be dynamic (DLLs), and of course executable .exe, but I also want to if static libraries are also included.
And please, if I'm wrong on any of my assumptions, please correct me.
In the first library project, FirstLib.h:
#pragma once
#include <SecondLib.h>
#ifdef DLLONE_BUILD
#define DLLONE_API __declspec(dllexport)
#else
#define DLLONE_API __declspec(dllimport)
#endif
int DLLONE_API MainOne();
int DLLONE_API InternalOne();
and FirstLib.cpp:
#include <FirstLib.h>
int MainOne() { return InternalTwo(); }
int InternalOne() { return 100; }
Similarly, in the first project, SecondLib.h:
#pragma once
#include <FirstLib.h>
#ifdef DLLTWO_BUILD
#define DLLTWO_API __declspec(dllexport)
#else
#define DLLTWO_API __declspec(dllimport)
#endif
int DLLTWO_API MainTwo();
int DLLTWO_API InternalTwo();
SecondLib.cpp:
#include <SecondLib.h>
int MainTwo() { return InternalOne(); }
int InternalTwo() { return 200; }
Finally, in the executable project, main.cpp:
#include <FirstLib.h>
#include <SecondLib.h>
int main() { return MainOne() + MainTwo(); }
So when compiling the two libraries, I obtain the two .dll files, and two .lib files. Each library must have the other library .lib to link.
Then, the executable must be linked with the two .lib, and when executed, .dll should be in a known path for the exe, be the same path or some PATH.
Now for the questions:
Is doing this a correct aproach, or should be avoided?
Exe needs the two dlls, but each dll needs the other dll. Does each dll loads the other one again, or uses the same loaded version from .exe?
If they were static libraries, would each library be loaded two times, or just one? Or none of them?
And if you have a good resource where I can find more about this, it will be really apreciated.
Thanks in advance!
UPDATE as why would I do this : Imagine creating an engine.
I have (just to be consistent with the previous scenario) a library called Kernel, and a library called System. Also a binary project.
Kernel has the code regarding program execution (main loop), handling, base clases and other high level things.
System has the code regarding HAL and low level code. OpenGL things, file IO things, etc.
Binary has the main function, and program specific implementation of the engine.
Why do I need that cross-linking:
Kernel in Binary: main() (Binary) calls Kernel.Initialize() (Kernel).
System in Binary: CreateActor()(Binary) calls System.OpenGl.MeshCreate() (System)
System in Kernel: Kernel.Initialize()(Kernel) Initializes the Kernel, but also the System by calling System.Initialize()(System).
Kernel in System: class System(System) inherits from class Object(Kernel)
I know i could avoid this circular dependency by, say, Initializing System from binary calling System.Initialize()after Kernel.Initialize().
But then, Kernel will depend on no one, System would depend on Kernel, and Binary on both Kernel and System.
So my question remains in this case too
Is removing the cross dependency but to have this scheme a better aproach?
Same as question two: Does Binary and System both depending on Kernel as well asBinary in System represents double code, double loading or a performance or size downgrade or some kind of undesirable effect?
I encounter a problem about UnsatisfiedLinkError.
My code is :
class ClassA
{
public:
static const int MY_ENUM_1 = 0;
};
I use Android Studio build my code to .a.
And then I write .so for link the interface of my lib via JNI.
I build the project successfully. But it occur an error about this while run-time,
java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "_ZN12LaChenEngine14GraphicsSystem22VertexBufferAccessList12DYNAMIC_DRAWE
LaChenEngine is the namespace.
GraphicsSystem is the namespace in LaChenEngine.
VertexBufferAccessList is my class for declaring all enum.
DYNAMIC_DRAW is one of enum in class VertexBufferAccessList.
Is this problem about version in ndk?
By the way, I develop my library on Windows Platform.
One possible cause is that one project defines a extern "C" function, and the other assumes that it is a C++ function.
More info: https://stackoverflow.com/a/1041880/755804
Another guess: check if that function is there in your .so, and if not, find out where it is.
In general, how I would approach such linkage problem is: I would start with a hello-jni application, adding one feature at a time (another library, C++ functions, C++ functions in name spaces, etc.)
I test many version of ndk, it still happen again and angin.
So I decide to change the code like this :
//.h
class ClassA
{
public:
static const int MY_ENUM_1;
};
//.cpp
const int ClassA::MY_ENUM_1 = 0;
And then, it work.
Thanks for all helps.
I am loading plugins (DLLs) dynamically at runtime using the Qt QPluginLoader class.
So far, I have successfully loaded plugins with functions that are called from the main program. Now, the plugins will need to call other functions in the main program. I've included the relevant header files in the plugin project, and it compiles without errors.
When I try to call the following plugin function from the main program:
// main program calling a function in a dll that has been dynamically
// loaded into the program:
PluginInterface* plugin = qobject_cast<PluginInterface*>(QPluginLoader(path)).instance();
plugin->DoSomething(); // works, writes a message to the console
plugin->callMainProgramFunction(); // not working
'
// test method in the plugin project (dll) that writes to console:
void TestDLL::DoSomething();
{
std::cout << "Hello, this messages comes from TestDLL! Have a nice day"; // works
}
'
// test method in the plugin project (dll) that tries to
// call a method in the main program:
void TestDLL::callMainProgramFunction()
{
Angle test; // angle.h is included, and offers geometric functions
std::cout << test.sine() << "\n"; // does not work, program stops
}
the program stops. I believe this is because the plugin does not know where to find the symbols (the code from angle.cpp that is linked and compiled into the main program), since it is linked into the program dynamically afterwards.
Many plugins will use the same functions, therefore I consider compiling each plugin with all the implementations a bad idea.
Is there a solution to this, using QPluginLoader? How can I tell the dynamically loaded plugins where to find symbols in the main program? I know that QLibrary offers a more manual way of exporting/importing functions and "resolve symbols", but lacks the neat instance functionality of QPluginLoader.
You can create a dll with common functions that are shared between the plugin and the main program, and link it in both the main program and the plugin.
QPluginLoader solves the problem that I described: Libraries that are loaded dynamically into the main program through QPluginLoader, will be able to call functions in the main program.
The cause to my problem was a subtle error in the plugin interface that I use.
It is possible, but don't forget on Linux to link the main program with the -rdynamic flag, so that symbols of the main program are visible from plugins.
Ok, I am very new in C++ development. This question may be silly but I can not find its response in any tutorial, book, question/response. It would be great if somebody can kindly explain it to me.
I have 1 header-source pair inside of a shared library libdummy.so:
This is dummy.h:
class dummy
{
public:
~dummy();
dummy();
bool dosomething(int a);
};
and this is dummy.cpp:
#include "dummy.h"
dummy::dummy()
{
//some assignments here
clear();
}
dummy::~dummy()
{
clear();
}
bool dummy::dosomething(int a)
{
// do something here
return true;
}
EDIT: I tell you above the sample codes of dummy.h and dummy.cpp but these files are not in my hand. They are packed inside the library libdummy.so. I have only the libdummy.so shared library file in the hand.
And I have a client to access my shared library.
client.h is here:
#include "dummy.h"
class client
{
public:
void myownjob();
dummy thingy;
//and some functions here
};
and finally this is the client.cpp:
#include "client.h"
void client::myownjob()
{
thingy.dosomething(1);
}
Now my problem is; when I try to compile this code, I get undefined reference errors to the constructor and destructor:
error: undefined reference to 'dummy::~dummy()'
error: undefined reference to 'dummy::dosomething(int)'
error: undefined reference to 'dummy::dummy()'
EDIT: The dummy.h and dummy.cpp are inside libdummy.so. I have only 3 files in the hand: libdummy.so, client.h and client.cpp.
That's why;
I can not delete ~dummy(); and dummy(); in the dummy.h to let the compiler creating them automatically. Because dummy.h is inside the libdummy.so shared library. It is not directly editable.
I can not do some braceleted empty definitions like ~dummy(){} and dummy(){} in the dummy.h. Because dummy.h is inside the libdummy.so shared library. It is not directly editable.
I can not include dummy.cpp to SRC_FILES line of my makefile. Because dummy.cpp is inside libdummy.so shared library. It is not a seperate file.
I think this is a very simple/beginner problem, but I can not find its response anywhere. What I have to do to use a class which is inside a shared library, in C++, when I get undefined reference errors to the constructors and destructors?
Thanks in advance.
I don't know about any NDK, but this error is a linking error - where you don't provide the library at link time (even though it's a dynamic library, you have to provide it when linking)
Normally I'd tell you to compile + link like this:
g++ client.cpp -ldummy
(-ldummy links with libdummy.so)
but given you're using some makefile you're not familiar with, I don't really know how you should do it. I can guess though:
Apparently you have a field named SRC_FILES. A quick (and incomplete) google suggest you have a field named LOCAL_LDLIBS. If so try setting this:
LOCAL_LDLIBS = -ldummy
Or, if the libdummy.so file isn't in your standard path:
LOCAL_LDLIBS = -L/dummy/file/path -ldummy
(/dummy/file/path is obviously the path of your dummy library)
Note that depending on your configuration, you might need to add the -L even if the file is in your working directory.
please compile both the file.. If you are using linux , than
g++ client.cpp dummy.cpp
I'm working with VC9 on Windows.
I have a library (lets call it libfoo) which is made of the following files ("include guards" and "#include" directives omited for clarity's sake):
// foo.hpp
class Foo
{
public:
static const std::string SOME_CONST;
};
And:
// foo.cpp
#include "foo.hpp"
const std::string Foo::SOME_CONST = "hello";
Foo::SOME_CONST is exported using a .def file.
The library compiles fine: a libfoo.lib file and a libfoo.dll file are generated.
I used this library in a sample program, like:
// main.cpp
#include <foo.hpp>
int main()
{
std::cout << Foo::SOME_CONST << std::endl; // std::bad_alloc here
return EXIT_SUCCESS;
}
A std::bad_alloc is thrown whenever I attempt to use Foo::SOME_CONST.
This only happens if I link dynamically to libfoo. Linking statically results in a perfectly working program.
What could possibly be going on here ? Is it legal to export a std::string constant that way ?
Check if dll actually does dynamic initialization, because it might not, standard has no requirements for dynamic libraries. Wrapping globals in static functions can be the solution.
Use __declspec(dllexport) and __declspec(dllimport). Stop worrying about .def files and all of that rubbish- let the compiler do the work.
Are the library and the main application linking to the same version of the standard library and/or CRT and/or MFC, with exactly the same settings? I've seen allocation issues when using different versions of the CRT, and also fought bugs caused by different iterator debugging settings between a library and its including application.