I am writting a game, and at the same time building an engine for it and for other games I may make in the future. During testing on both the game logic and the engine (separately) run well. However when I try to link them together, I encountered some problem with the inclusion of header files.
To be specific, here is what I did:
The engine is built as Static Library (.lib), and depends on GLFW static library (glfw3.lib). It contains a Window.h file:
// Window.h
#pragma once
#include <glfw3.h> // include other library's header
#include <iostream>
//test if the linking success
void test() {
std::cout << "this is Window.h";
}
class Window
{
// Window class code (declaration, function prototype, etc...)
}
*Note that the location of GLFW library is separated from engine/game project location.
The game project is hosted under the same Solution with the engine project. In the game's Properties, I have add the engine as dependencies as well as engine's .lib and include location. Then I try the following:
// game's main file
#include <Window.h>
void main()
{
test(); // call the test function from Window.h
}
When building the game, I got an error says that it can not find such file called "glfw3.h". However, if I comment out the inclusion of glfw3.h in Window.h file:
# Window.h
#pragma once
//#include <glfw3.h>
then the game build and run normally, and prints out the test line in test function.
I want to build the engine as a single .lib with header files that prototypes functions for its classes; so that in the game project I only need to include/depend the engine library and no need to care about GLFW or such. How can I achive that?
I found a similar question, but it seems the answers don't solve my question.
You could try the suggestion from the related post below. Basically build your library as you are doing then statically merge it with the glfw static lib.
How to merge two windows vc static library into one
Related
So when you #include a header in C++, the compiler just copies the content of the header and pastes it where the #include was. I'm making a small game engine/framework and I'm including GLEW & GLFW in my Engine.h because I need things like GLFWwindow. But I get a compiler error in my Test Game 1 Project that uses the engine because since the compiler is just copying the code form engine.h and pasting it in test game 1's main.cpp, It's trying to include glew and glfw in my test game 1, which I don't want it to and I haven't linked against the glew and glfw libs in that project. How do I fix it so I can still access glew and glfw in engine.h without including them in test game 1?
You have two options.
1. Either you statically link your project with glew and glfw libraries and then call GLFWwindow function
2. Or you load glew and glfw libraries in the c++ code using LoadLibrary() and then call GLFWwindow function using GetProcAddess()
So I'm trying to create my own library in C++ and use it in another project.
So far it works with example code, but I have to include other libraries in my own library. So the problem is, that when I include the header files off my library,
the include paths in the header files are messed up.
A simple solution would be to add the search directories, but I don't think,
thats how its supposed to be resolved.
Sample Code - Library header file:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
int test();
The source file:
#include "sample.h"
int test() { return 20; }
Now the project in which I want to include the sample
#include <sample.h>
int main() { int a = test(); }
The problem is, that the include copies the code from sample.h directly into the main.cpp and the search directories for the other includes from sample.h are no longer defined
A simple solution would be to add the search directories, but I don't think, thats how its supposed to be resolved.
This is certainly the easiest solution since it requires no modifications to the code, and is usually an acceptable thing to do - however obviously it means the project can call the functions from glew.h and glfw3.h
The only alternative is to ensure the headers are not included by the library header, but instead by the source.
IE:
Library Header:
int test();
Library Source:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "sample.h"
int test() { return 20; }
And the project's source file left unchanged.
This requires that the types defined in glew.h and glfw3.h are not part of the public interface exposed by your library.
Eg, if your library had a function like:
GLFWwindow* window = openWindow(...);
You would need to change it to:
Library header:
struct WindowHandle;
WindowHandle* openWindow(...);
Library source:
struct WindowHandle{
GLFWwindow* window;
};
WindowHandle* openWindow(...){
WindowHandle* result;
//... do stuff...
result->window = //whatever;
return result;
}
This approach requires changing the library code, but has the advantage that the users of the library can't directly call the things the library depends on (glew and glfw in this case). This is particularly beneficial if you want to support multiple platforms, you could have a source file for opening windows via glfw, and another using direct x. The library's public interface would not need to be changed to support both backends.
If you want to know more about this approach try searching for "Opaque data types"
I am currently trying to get my head around library linking with Qt in order to split up some existing code into logically structured modular parts that can be called by different applications.
I keep getting a problem where no obj files are being created... so I have created a smaller sample project and replicated my problem below.
It seems, to me, the problem lies in the library ...so I will start there.
If I have code like this, the obj file is created (and can therefore be linked to by my test application):
mylib.h
#ifndef MYLIB_H
#define MYLIB_H
#include "mylib_global.h"
class MYLIB_EXPORT MyLib
{
public:
MyLib();
~MyLib();
private:
};
#endif // MYLIB_H
mylib.cpp
#include "mylib.h"
MyLib::MyLib()
{
}
MyLib::~MyLib()
{
}
But if I remove the cpp file and just have the header file with function bodys included (as is the structure of my actual codes library as the code consists ONLY of templates), nothing is created:
mylib.h
// .......
public:
MyLib(){}
~MyLib(){}
// .......
How can I get Qt to build my code please?
If your library is just a header file, you don't need to compile it, include your headers in your other projects, and they will be compiled into it.
After a day of banging my head against the wall both literally and metaphorically, I plead for help:
I have an unmanaged C++ project, which is compiled as a DLL. Let's call it CPP Project. It currently works in an unmanaged environment. In addition, I have created a WPF project, that shall be called WPF Project. This project is a simple and currently almost empty project. It contains a single window and I want it to use code from Project 1. For that, I have created a CLR C++ project, which shall be called Interop Project and is also compiled as a DLL.
For simplicity I will attach some basic testing code I have boiled down to the basics.
CPP Project has the following two testing files:
tester.h
#pragma once
extern "C" class __declspec(dllexport) NativeTester
{
public:
void NativeTest();
};
tester.cpp
#include "tester.h"
void NativeTester::NativeTest()
{
int i = 0;
}
Interop Project has the following file:
InteropLib.h
#pragma once
#include <tester.h>
using namespace System;
namespace InteropLib {
public ref class InteropProject
{
public:
static void Test()
{
NativeTester nativeTester;
nativeTester.NativeTest();
}
};
}
Lastly, WPF Project has a single window refrencing Interop Project:
MainWindow.xaml.cs
using System;
using System.Windows;
using InteropLib;
namespace AppGUI
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InteropProject.Test();
}
}
}
And the XAML itself has an empty window (default created).
Once I am trying to run the WPF project, I get the following error:
System.Windows.Markup.XamlParseException: 'The invocation of the constructor on type 'AppGUI.MainWindow' that matches the specified binding constraints threw an exception.' Line number '3' and line position '9'. ---> System.IO.FileNotFoundException: Could not load file or assembly 'InteropLib.dll' or one of its dependencies. The specified module could not be found.
at AppGUI.MainWindow..ctor()
Interestingly enough, if I do not export the class from CPP Project, I do not get this error. Say, if i change tester.h to:
#pragma once
class NativeTester
{
public:
void NativeTest()
{
int i = 0;
}
};
However, in this case I cannot use my more complex classes. If I move my implementation to a cpp file like before, I get unresolved linkage errors due to my not exporting my code. The C++ code I want to actually use is large and has many classes and is object oriented, so I can't just move all my implementation to the h files.
Please help me understand this horrific error I've been trying resolve without success.
Thanks.
This went wrong right from the start, your tester.h file is not correct. The class should only have the __declspec(dllexport) attribute when you are building the tester project. Any other project that uses the DLL must see the class with the __declspec(dllimport) attribute. Start fixing this by using a macro in tester.h:
#undef EXPORTED
#ifdef BUILDING_DLL
# define EXPORTED __declspec(dllexport)
#else
# define EXPORTED __declspec(dllimport)
#endif
class EXPORTED NativeTester {
// etc..
};
And in your tester project, use C/C++, Preprocessor, Preprocessor Definitions and add BUILDING_DLL.
Next thing is to make sure that the DLL is being stored in the right directory. Which is what the exception is complaining about, it can't find the DLL. The build directory for C++ projects is Debug but for WPF projects it is bin\Debug. Fix that by changing the General + Output Directory setting, make it $(SolutionDir)$bin\(ConfigurationName).
Build the C++ project and verify that you can find the DLL back in the Solution's bin\Debug directory. And check that you also have the .lib file, you'll need that when you build the C++/CLI project. As an extra verification step, run Dumpbin.exe /exports foo.dll from the Visual Studio Command Prompt and check that you indeed see the class getting exported.
The C++/CLI project next, you need to change the Output Directory setting the same way. Add the .lib file to the linker's Additional Dependencies properties. You'll get the kind of linker errors you were talking about if you skip that step. Build it and verify that you get the DLL in the correct bin\Debug directory again.
Repeat these changes for the Release configuration.
Set the project dependencies, the WPF project depends on the C++/CLI project. The C++/CLI project depends on the C++ project. This ensures the projects are getting built in the right order.
You should now have a good shot at using these DLLs in your WPF project.
I have a simple C++ project that is structured as following:
-A base project (ie: contains main() ), and links against everything else
--A few custom libraries that are all built as static libs (ie: .a files)
---One of these static libraries uses features in a shared objective file (ie: a .so file)
So, for example, this is how the project would appear (in a a tree view) at link time, after all the initial compiling has completed:
-myApp (the main application)
--libaudio.a (the audio library I made)
--libnetwork.a (the networking library I made)
--libvideo.a (the video library I made)
--libboost.a (boost library)
Initially, this project build just fine. I just had to make sure I had a simple line in my makefile like this:
LIBS+=audio network video
Recently, I had to change how my audio library works. I now am required to use a third-party library, and all I have is the header file (.h) and the shared object (.so) files. So the new structure at link time looks like so:
-myApp (the main application)
--libaudio.a (the audio library I made)
---libthirdparty.so (contains third-party audio handling functions)
--libnetwork.a (the networking library I made)
--libvideo.a (the video library I made)
--libboost.a (boost library)
This, in effect, means that I have an application with a static library linked in which makes calls to an external shared object. So, I put the header file in the appropriate location so I don't have any build errors when compiling libaudio.a, and put the libthirdparty.so file in a location where the linker searches for all my installed libraries.
At this point, I cannot get the thing to build. It just doesn't see libthirdparty.so file, even though I know it is in a location that the linker searches by default. For some reason, wrapping my libaudio code, as in the example below (borrowed from www.cplusplus.com) fixes the build error:
my_C_CPP_Header.h:
#ifndef MY_C_CPP_HEADER
#define MY_C_CPP_HEADER
/*check if the compiler is of C++*/
#ifdef __cplusplus
extern "C" {
int myOtherCfunc(int arg1, int arg2); /* a C function */
}
#endif
void myCppFunction1(); /* C++ function */
void myCppFunction2(); /* C++ function */
/*check if the compiler is of C++ */
#ifdef __cplusplus
}
#endif
#endif
Now, I have a new problem though. Now that it's building, it no longer statically links in libboost.a, and instead is crashing at startup due to libboost.so not being present. So, somehow this setup breaks how libboost is compiled in if I manage to get it to build at all.
Any suggestions are welcome. Thank you all in advance.
In the end, there was a "LIBPATH=" instead of a "LIBPATH+=" statement overriding the library include paths. Resolved.
Thank you all for your help.