I have a dynamically linked linux executable that uses shared libraries. One of those libraries has a function that is used by other functions in that library - the object code of that function is contained in this library. I would like to provide alternative implementation of that function, so that instead of calling the original code that is in the library, those other functions would call my code.
Any way to do it?
Cannot do it without compiling the library with new changes.
If those functions are global or static functions, definitely you have to recompile.
If those functions are virtual member functions and if your application/library has hooks/expandability or factory kind of thing to new a derived object to the applications you can change it.
Otherwise you have to recompile the library code.
Related
I have a library that provides a function func():
return_type func(type arg);
It was necessary to override it by my own implementation in my application. It was possible because the library provides a weak symbol func while the func symbol in my application is a strong one. (That is my understanding.)
Now I want to be able to call both implementations of func - library's implementatoin and my own implementation:
// The problem is that the names are the same.
func(); // Everything is OK, calling my implementation (in my application)
func(); // How can I call library's implementation now?
I can call my implementation because it overrides the implementation in the library. But how can I call the implementation in the library? How can I refer to it?
If the functions are in shared libraries, you can load them with dlopen and the obtain the symbols from dlsym. You can then have different function pointers for for the functions from each library.
If the functions are in a static library, you will need to modify the static library to change the name. This can be done with something like objcopy --prefix-symbols=foo_ foo.o. Not sure if this can be done directly on a .a in such a case, you might need to expand the archive.
Having added the prefix you will then need to modify any header files to take the new names either using a macro or something similar.
I'm writing this Editor.exe program that loads a game.dll, gets the address of a function inside the dll, and pass a pointer to a Core object.
gameInitFuncPtr init =
(gameInitFuncPtr) GetProcAddress(LoadLibraryA("game.dll"),"gameInit");
init(&core); // core is already instanced somewhere, maybe on the stack
The game.dll includes the core.h where the Core class is defined.
The Core class is implemented and compiled into Editor.exe.
On the dll side, calling functions from the passed object pointer, results in an Unresolved external symbol
An example of a call the game.dll would do with the given object pointer would be:
void gameInit(ldk::Core* core)
{
_core->renderer.drawText("initializing...");
}
How can I compile the dll so that it does not try to find, for example, the drawText() implementation within the dll module ?
1 - Please, note that this is NOT a question about how to declare pointers to member functions.
2 - I know it could easily be fixed if i passed a struct with only pointer to the methods, but I'm really curious about this.
3 - I'm using Microsoft's cl compiler 18.00, the one that ships with Visual studio 2013
It is not clear where you initiallize _core. At first glance gameInit should do it.
Declare interface class Core, i.e. it should be abstract. Implement it in a successor class for example CoreImpl in exe. This will fix Unresolved external symbols.
Looks like I was overthinking it.
Wen compiling the editor.exe the Core sould be declared just link any class.
struct Core
{
struct Renderer
{
void drawText(const char* text);
}
...
}
But, since the editor and the game.dll share the same Core.h, I used a macro to modify the declaration of Core.h member functions to be pure virtual, for example:
struct Core
{
struct Renderer
{
virtual void drawText(const char* text) = 0;
}
...
}
So the Unresolved external symbol linking error is gone
BUT: I does not work as expected in RUNTIME! :(
I had a similar problem as you with almost the same setting - Game as dll and Engine as exe. Here are some notes on how to tackle this problem.
Call only virtual methods. As you pointed out, if the method you call is not declared virtual, the linker tries to find an implementation for it and fails (if it's not in the header - a thing we try to avoid). The method does not need to be abstract, virtual is enough. Also, note that in your struct Renderer you can have methods that are not virtual, as long as you don't call them from the dll (if you do, the linker complains). It is probably not advisable to have such an interface, it would be much better to have some sort of API class which has only virtual public methods so users of this class cannot make a mistake.
All classes used from the dll need to be shared or header only. What I mean by this is, that as far as I know, there is no magic way, to have classes declared in header, implemented in cpp which is compiled to the exe and then use these classes from the dll. E.g., if you have a custom string class, it needs to be in a shared library. If it's just in the exe you will not be able to instantiate it in the dll (return it from functions etc.). A solution to this is to use header-only classes. E.g., your string may be implemented in a header in the Editor project and this header may be included by your Game project. This way you essentially compile the same code to both exe and dll.
To see a small working example see my repository with VS 2017 solution which demonstrates this exact problem and nothing else. repo link.
Much larger working example of this problem can be seen in idTech4 engine - DOOM 3 version here. It also uses a game as a dll and an engine as an exe. And also needs to exchange pointers to the engine's systems which are used from the game. The project is big, but if you take a look at project Game-d3xp class Game.h all the way down, they have the game's API with a single function GetGameAPI_t which expects to get gameImport_t struct with pointers to engine systems and returns gameExport_t with game informations. The loading then happens in the Common.cpp
As you can see they use shared library idLib in the respective project for things such as idString. All engine classes used from the dll are usually very small and implemented in headers only (they are mostly structs).
Note that id themselves are moving away from this architecture and even their latest version of DOOM 3 - DOOM 3 BFG edition compiles to a single exe and the modules are static libraries instead of dlls.
I have a library libxx and inside that library there is a static function foo().
I want to write another function bar() which uses the function foo() as a subroutine.
Is there any way to do it without writing bar() on the file which the function foo() sits on and rebuilding the library?
Declaring a function static within a translation unit (object file / library) pretty much invalidates any assertions about that function's implementation. It could be completely inlined. It might use short-cuts with the calling conventions that would be incorrect when called externally.
On some OS/ABIs, the function will not be 'visible' in the sense that a .globl directive with ELF/Mach-O would provide, and the linker will prevent it, or the loader won't resolve it. In a shared library, it might not preserve position-independence outside its local use. The point is, you just can't do this safely or portably.
In short, you need to recompile the function as non-static, i.e., a global / visible symbol in the library, or have a static version available to your bar() function. Say, via static inline.
It sounds like you have the source code to libxx. If that's the case, and you'd like bar() to exist in the same library as foo() then you'll need to recompile libxx after adding bar() to it.
If your goal is to call libxx::foo() from another program/library then you can just link libxx to your other project (which has bar() in it). Once the library is linked to your main project all you need to do is call into the correct namespace and invoke foo(). Linking a library to your main project will require using a linker. Different development systems will have different ways of invoking the linker. For researching this further, I would advise that you search for "c++ linking to static library X" where X is your development system (ex: visual studio, xcode). I'm assuming this is a static library based on the tag you put on the question, but maybe you meant that foo() was a static method. It shouldn't matter if it's a static method or not, linking will work in the same way. If you are confused about what I mean when I write "static library" then maybe researching the difference between static and dynamically linked libraries will clarify.
Not within standard C/C++.
The function has an address which is callable or other functions which may allow the foo to be called indirectly.
But these are bad solutions
I am trying to handle a project with multiple dynamic libraries, in the libraries some global objects are created and registered in a list so that the executable can use them to build other things. In the executable there's no reference to any function of any library, it just needs the objects, and then it knows what to do. These libraries are intended to work like plugins that are chosen at link time.
Ideally when compiling ExecutableProject I link LibraryA, an object of type A gets created (by some code that's compiled in the library) and ExecutableProject does things because of it, using functions in LibraryA. If instead I link LibraryB then an object of type B gets created and other things happen.
The problem is, since ExecutableProject does not directly use any function or class in the library, the library is not loaded, and objects are never created.
I have found some workarounds:
I can use /INCLUDE:symbol at link time when compiling ExecutableProject, where symbol is any symbol exported in LibraryA or LibraryB. I don't like this because I have to know the decorated name of a function in the library, which is not always available. Also, it's not elegant.
I can use a dummy variable. I could put __declspec(dllexport) int force_link_A_or_B; in LibraryA and LibraryB and __declspec(dllimport) extern int force_link_A_or_B; in ExecutableProject. I don't like this because if I had more libraries I'd have to add a variable for each of them. Basically although the code in ExecutableProject does not know which libraries will be linked, it still needs to know how many of them can be linked together.
On Linux, using gcc and ld, it's very easy to solve this problem, all it takes is a simple linker flag -Wl,--no-as-needed. Is there any way to do this using Visual Studio? I would be happy if there was something that worked like /INCLUDE but used entire libraries instead of symbols and did not need decorated names.
Thanks
EDIT: I have been asked to clarify how this design is intended to work. Ideally, when I compile ExecutableProject I link LibraryA or B and an object is created.
`ClassA A;`
This is placed outside all functions in a source file that is compiled in LibraryA. Same thing happens in LibraryB. The key here is that ClassA and ClassB inherit from a BaseClass that ExecutableProject knows well. When the object is created, the BaseClass constructor is run, and inside it a BaseClass* pointer pointing to this (therefore the derived object) is saved, and ExecutableProject uses that pointer. It does not need to know anything about the derived classes, because it uses only a BaseClass pointer, but when it calls virtual functions from it, different functions are executed depending on the actual type of the pointed object. If there were more objects instead that just two alternatives, I would save BaseClass pointers in a list or a map, and let ExecutableProject access it.
Don't try this. The design is fundamentally flawed.
In particular, since you are not making any explicit calls to the DLL, you would rely only on object A being created via an implicit call to DllMain.
But under Windows rules, you are barred from doing anything interesting in or from DllMain, so object A cannot be very useful.
I've got an application that's using a static library I made. One .cpp file in the library has a static variable declaration, whose ctor calls a function on a singleton that does something- e.g. adds a string.
Now when I use that library from the application, my singleton doesn't seem to contain any traces of the string that was supposed to be added.
I'm definitely missing something but I don't know what..
If you have an object in a static library that is not EXPLICITLY used in the application. Then the linker will not pull that object from the lib into the application.
There is a big difference between static and dynamic libraries.
Dynamic Library:
At compile time nothing is pulled from the dynamic library. Extra code is added to explicitly load and resolve the symbols at run-time. At run time the whole library is loaded and thus object initializers are called (though when is implementation detail).
Static libraries are handled very differently:
When you link against a static library it pulls all the items that are not defined in application that are defined in the library into the application. This is repeated until there are no more dependencies that the library can resolve. The side effect of this is that objects/functions not explicitly used are not pulled form the library (thus global variables that are not directly accessed will not be pulled).
My memory of this is a bit hazy, but you might be getting hit with an initialization order problem. There are no guarantees in which order static variable initializers in different files get called, so if your singleton isn't initialized yet when your static variable in the library is being initialized, that might produce the effect you're seeing.
The way I've gotten around these problems is to have some sort of an explicit init function that does this stuff and that I call at the start of main or something. You might be able to fiddle with the order in which you give the object file and library arguments to the compiler (or linker, actually) because that's also worked for me, but that solution is a bit fragile because it depends not only on using the specific linker but probably also the specific version.
Refactor the classes doing static initialization so they do not depend on any other such classes. That is, make each class's initialization independent and self-sufficient.