C++ - Linking third library functions in static library - c++

I'm creating an C++ static library with code::blocks that call functions of the SDL library. The library compiles OK. I created annother project that will use the library I've created, all the build options are OK, I set the linker to work with the SDL and everything else, but, when I try to compile the project, I got Undefined Reference in the SDL functions. I solve this trouble by putting an call to SDL_Delay(1) function in the end of the main function.
It seems that the linker only found the SDL functions when I call at least one of them in the project that I'm compiling. Exist an more correct way to solve this?­
example:
#include "HW_Engine" // My static link library
void main(int argc, char *argv[]){
HWE_Core *Engine_Core = new HWE_Core(); // this constructor calls some SDL functions
...
SDL_Delay(1); // If I omit this, I have an Undefined reference for all the
// SDL functions called in the HW_Engine library
}
thanks for the help!

Related

CoInitialize has not been called - (loading gamepad.h from DirectXTK without library)

I am using the DirectXTK library for the gamepad class. I compiled the library with only this class inside it and it works.
If I would only add the source files to my project, without the library, the size would be ~50KB instead of ~500KB. However, I am receiving the following error:
CoInitialize has not been called
Any ideas on how to resolve this so my executable would be smaller in size?
Well, you could call CoInitialize yourself as the first thing in main.
int main()
{
CoInitialize(NULL);
// your code
return 0;
}

Calling main program functions from a dynamically loaded library (QPluginLoader)

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.

unresolved external symbol __imp__glewInit VS __imp__glewInit#0

When I use opengl in my program, I come acrross a problem when using "glew": unresolved external symbol _imp_glewInit (when use the glew 1.10.0), as I replace the glew32.lib by version "glew 1.6.0", this problem is solved. However, when I compile the attached simple code in a .cpp file, link step fails with an error: external symbol _imp_glewInit#0. Then I use VS2008's dumpin.exe to inspect glew32.lib in glew 1.6.0 and glew 1.10.0, it turns out glew 1.6.0 has a symbol named _glewInit while glew 1.10.0 has _glewInit#0.
So my question is why these two glew32.libs have different symbol names? If I want to use the new features in glew 1.10.0 and has the error "unresolved external symbol _imp_glewInit", what is the best way to solve it?
#include "glew.h"
#include <GL/freeglut.h>
int main(int argc, char **argv){
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
glutCreateWindow("123");
GLenum err = glewInit();
return 0;
}
PS: All my test is on Win7, the compiler is VS2008_SP1.
#0 is the name decoration scheme for a __stdcall function that is passed 0 bytes worth of arguments (in other words, a void function). Use the proper header that ships with your library so that it uses the calling convention the library was compiled with. In this case, whether you use C or C++ linkage (as suggested in comments) makes no difference because the __stdcall calling convention always adds the underscore at the beginning of the symbol name.
Regarding _imp_glewInit that is another matter entirely, as that is the DLL import stub. In the end, there is almost no real benefit to using the DLL version of GLEW. So I suggest you use the static linking version: glew32s.lib and define GLEW_STATIC to make things easier in the long-run.
To answer your final question: there are no new features in GLEW that you can use just by dropping in a new version of the DLL, your program has to be aware of the extensions GLEW loads when you actually write the code. If there is no code that takes advantage of one of the new extensions, then nothing is gained. This is why the DLL version of GLEW offers nothing special vs. the static library.

C++:Undefined reference to 'FMOD:: X'

After looking around for various sound API libraries, I have decided to use FMOD for the time being.
Problem is that whenever I try to compile one of the code examples, I get the following errors:
obj\Release\main.o:main.cpp|| undefined reference to `FMOD::System::getVersion(unsigned int*)#8'|
obj\Release\main.o:main.cpp|| undefined reference to `FMOD::System::init(int, unsigned int, void*)#16'|
obj\Release\main.o:main.cpp|| undefined reference to `FMOD::System::createSound(char const*, unsigned int, FMOD_CREATESOUNDEXINFO*, FMOD::Sound**)#20'|
obj\Release\main.o:main.cpp|| undefined reference to `FMOD::Sound::setMode(unsigned int)#8'|
The code example that I am using being this:
#include <D:\Games\FMOD Programmers API Win32\api\inc\fmod.hpp>
#include <D:\Games\FMOD Programmers API Win32\api\inc\fmod_errors.h>
#include <sstream>
#include <windows.h> // for PlaySound()
#include <time.h>
#include <mmsystem.h>
using namespace std;
int main(int argc, char* argv[])
{
FMOD::System *system;
FMOD::Sound *sound1, *sound2, *sound3;
FMOD::Channel *channel = 0;
FMOD_RESULT result;
int key;
unsigned int version;
/*
Create a System object and initialize.
*/
result = FMOD::System_Create(&system);
result = system->getVersion(&version);
result = system->init(32, FMOD_INIT_NORMAL, 0);
result = system->createSound("../media/drumloop.wav", FMOD_HARDWARE, 0, &sound1);
result = sound1->setMode(FMOD_LOOP_OFF); /* drumloop.wav has embedded loop points which automatically makes looping turn on, */
/* so turn it off here. We could have also just put FMOD_LOOP_OFF in the above CreateSound call. */
// Code continues into other bits that work...
I am using the latest version of FMOD and am using the Code::Blocks IDE (ver 10.05), with the GNU GCC compiler. The project is of type "Console application". The fmodex.dll file is in the folder of my project. I am using windows XP 32 bit SP3.
I have linked to the libfmodex.a library and have tried linking to the other libraries it has there as well, but this does not solve the problem.
My question is, therefore, what do I need to do to stop these errors occurring? As when I encountered similar "Undefined reference to x" errors before using other libraries. I had just forgotten to link to them in Code::Blocks and as soon as I did, they would work.
Do say if you need more information regarding the code etc.
When using FMOD with Code::Blocks you need to use the C API, not the C++ API. FMOD is built with Visual Studio, therefore the C++ symbols use the VC mangling scheme. There is a note in the "Getting Started with FMOD for Windows" document that mentions this.
http://en.wikipedia.org/wiki/Name_mangling#How_different_compilers_mangle_the_same_functions
I do not have a Windows box ready to verify this on, but try replacing those backslashes with forward slashes in the include paths, or escape the backslashes.
#include <D:/Games/FMOD Programmers API Win32/api/inc/fmod.hpp>
#include <D:/Games/FMOD Programmers API Win32/api/inc/fmod_errors.h>
or
#include <D:\\Games\\FMOD Programmers API Win32\\api\\inc\\fmod.hpp>
#include <D:\\Games\\FMOD Programmers API Win32\\api\\inc\\fmod_errors.h>
(Or, better, just add D:\Games\FMOD Programmers API Win32\api\inc\ to your list of include paths, and include the files by filename instead of full path; then your code might actually compile somewhere other than your specific computer!)
Those undefined reference errors mean that the compiler, or rather the linker part of the compiler, cannot find the library.
I don't use Code::Blocks so I don't know where the setting is, but you need to tell your project to use the library and where to find it.
Just putting the DLL in the directory is enough for running the program, but for linking it you need a .lib file.

[windows] back linking

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.