Linking a static library to a new project in Visual C++ - c++

I am just beginning to learn C++ and using Visual Studio 2017 as the IDE. I want to stay away from the CLR, and even Windows specific code as much as possible. Every new project option seems to say 'Windows', and thus suggest Windows OS dependencies, except for General > Empty Project, so that is the option I have chosen.
I am trying to write a static library with some functions. Here's a simple example of what I'm trying to do.
//Lib1.h (Project A)
#pragma once
#ifndef LIB_H
namespace Lib1
{
double Add(double, double);
}
//Lib1.cpp (Project A)
#include "Lib1.h"
namespace Lib1
{
double Add(double a, double b)
{
return a + b;
}
}
//Main.cpp (Project B)
#include "Lib1.h"
using namespace Lib1;
int main()
{
double c = Add(1, 2);
}
Project A compiles without warning/error. I changed the Project Properties > General > Configuration Type to be Static Library (.lib), but I cannot actually find the compiled .lib file in the project directory, just an .obj file.
When I try and build Project B it throws the following error message.
"LNK2019 unresolved external symbol "double __cdecl FrameTransformations::Add(double,double)" (?Add#FrameTransformations##YANNN#Z) referenced in function _main FrameTransformationTests S:\Projects\Cpp\Code\FrameTransformations\FrameTransformationTests\Main.obj 1"
I've had a look and it seems that project B can't find the Add function from project A, although I get auto-completion for the function and arguments through Intellisense (is this just because it can find the Lib1.h file ok?).
I have tried adding in the path to the Project A folder in the Project B Properties > C/C++ > General > Additional #using Directories (both to the Project folder and to the Debug folder where I expected the Lib1.lib file to be generated), but that hasn't worked.
Can someone please point me to what I've done wrong, this has had me stumped for a couple of hours now.
Thank you.

The .lib file is generally under the solution directory rather than the more specific project directory:
Look in \ or possibly \\.

When you #include a .h file, you are usually just including declarations into your code (exceptions apply, but not in this case). These are separate from definitions which are placed into .cpp files.
By default your projects do not automatically shared any of this information with each other. Your definitions nor declarations from Project A do not magically propagate to Project B, for example.
But as you've done here, you can reference declarations from Project A into Project B by #includeing header files. These, however, are just declarations! They just explain the existence of a function but don't implement it -- You need to add the definition of your Add function to Project B.
The process of bringing such definitions together is called linking. You need to link the definitions of Project A (the .lib, more precisely) into Project B. The way you do this changes with each version of Visual Studio just slightly, but it's usually under some "Linker Options" and some "Dependencies" tab/window.

You need to add reference of Project A into Project B->Project Properties as below,
Also, you need to add a reference in like below

Related

Trying to create Library in C++. Test project can't find implementation of declared constructor?

I'm learning C++, but hit a plateau trying to create a library. Using Visual Studio 2013, I get this error:
Error 1 error LNK2019: unresolved external symbol "public: __thiscall Polynomial::Polynomial(void)" (??0Polynomial##QAE#XZ) referenced in function _main A:\Medier\Desktop\PolyLib\Test\Test.obj Test
The testproject is currently cut down to this:
#include "A:\Medier\Desktop\PolyLib\PolyLib\PolyLib.h"
using namespace std;
void main()
{
Polynomial poly;
}
The library header file, PolyLib.h, looks like this:
using namespace std;
class Polynomial {
private:
double* Coefficients; //Array of coefficients - Pointer type.
int Degree; //The highest exponent of the polynomial
public:
Polynomial(); //Default constructor - Creates the trivial polynomial 0.
Polynomial(int degree, double coefficients[]); //Constructor for specific polynomials
Finally there's a CPP file in the library, PolyLib.cpp, providing implementations for the header file. Looks like this:
#include "PolyLib.h"
using namespace std;
Polynomial::Polynomial() {
Degree = 0;
Coefficients = new double[Degree + 1];
Coefficients[0] = 0;
}
Polynomial::Polynomial(int degree, double coefficients[]) : Degree(degree), Coefficients(coefficients) {
int i = 0;
}
I understand that my test project looks to the PolyLib.h file to see what stuff is available. And I understand the error says it can't find the actual implementation of the empty constructor for Polynomial. As such I conclude that the PolyLib.cpp file is not being used.
Can anyone tell me where I go from here?
It is possible to build all of your .cpps into a single project, which is most common for beginners. However, from the question tags and wording, I'm assuming you want to create and link a static lib, which can also be done fairly simply.
I just constructed an example of a properly set up static lib + exe linking in one VS2013 project: Dropbox link, for the purposes of explaining this question.
The basics are that you need two projects: A lib project (outputs a static .lib file) and an exe project (outputs an .exe file). The .exe project contains a main() function, and is able to include headers and link to the .lib.
The points of interest in MyExe are that I added $(SolutionDir)\LibExample\Inc to the include path in order to include my header (header.h), and I added $(SolutionDir)\$(Configuration) to the lib path for the libraries. You can find these by right clicking the project, go to properties, and it's all under "VC++ Directories".
A great tip about determining the path needed to find your lib is to simply build the lib. It actually tells you in the "Output->Build" text spew where the file it just built is located. This is the path that you need. $(SolutionDir)\$(Configuration) is the "macro" shorthand of this path. I recommend using the macros so you can move your project directory to another path or computer easily.
I also added LibExample.lib; to "additional dependencies" in the linker\input settings. This is the key step for being able to link the lib. Not doing this will result in an unresolved external symbol, just like you're seeing.
I also set a dependency between MyExe and LibExample (you right click the project, Build Dependencies->Project Dependencies). This is important so you can rebuild the entire solution without worry of linking to the older version of the lib. With the dependency in place, it will always build the lib first, then the exe.
If you are trying to build Polylib.h and Polylib.cpp into a binary such as Polylib.lib then you need to have a separate project that has these source files and builds a static library. Then you need your project to link this Polylib library so that it can link the code into your binary. If you just want to have one project and only build one binary then you need to move the Polylib.h and Polylib.cpp source into your project and build it all together. Another thing is that using absolute paths for including headers is a bad idea. You want to include headers using relative pathing and then use the project settings to tell it where the headers are located. For example if its local to the project then use #include "header". If its not local to the project then use #include <libraryfolder/header> and then tell the project where the library folder is in the "include directories setting".

unable to link header and cpp file of one project's from another LNK2019: unresolved external symbol error

I have a header file A.h
namespace DIV
{
int Fun();
}
A source file A.cpp
namespace DIV
{
class A
{
public:
A(){}
~A(){}
int Fun();
};
int A::Fun()
{
return 0;
}
}
Now I have another source file B.cpp in another project of the same solution.
This source uses google's GTest framework. Inside the test function I use
#include "gtest/gtest.h"
#include "A.h"
TEST(FunTest, Param)
{
int value = DIV::Fun();
}
Because of the DIV::Fun() call I get linker error. I don't understand the reason behind the linker error.
EDIT: B.cpp is in an .exe project and A.h/cpp is in a lib project.
Problem is solved. I have got the answer from here. To summarize I needed to link my exe project with the lib project which contains the function fun(). Now the simplest way to make the .exe project link against .lib project probably is by adding a reference:
In the .exe project's settings, select the section named "Common Properties" at the top of the section list.
You should now see a list of references that the .exe project has. The list is probably empty.
Click the "Add new reference" button at the bottom of the dialog and add the .lib project as a reference
When you select the new reference in the list of references you will see a set of properties for that reference. Make sure that the property called "Link Library Dependencies" is set to true. This will cause the .lib project to be added automatically as an input to the linker when you build the .exe project.
After that the linker error was gone.
With extern and without extern keyword it works. You need to export your function fun to other modules/projects. Use __declspec(dllexport) .
What is the purpose of your use of extern here? Because functions have external linkage by default, marking functions extern for this reason is not necessary. However, this should not cause a linker error in this case.
The linker error indicates that the function definition is found but the object file is not properly linked. How are you compiling and linking the program?
EDIT:
Since A.cpp is not in the same project as B.cpp, you will need to explicitly link to the object files in your A.cpp project. Since it sounds like you are using Visual Studio, you may find this useful
How do you share code between projects/solutions in Visual Studio?

Unresolved external symbol from a static library in one project, not the other. (C++)

I have a static library that compiles fine (lets call it A), and it is reliant on another static library (lets call it B).
I also have project X, which uses library A. So in X I include B and then, below it, include A, both in stdafx.h. I do this using #pragma comments. Project X compiles fine.
However, I then have project Y which also uses library A. But, even though project Y's stdafx.h is IDENTICAL to X's, Y does not compile, giving "unresolved external symbol" errors. What is even stranger is that the errors refer to a function in library B from a function referenced in library A.
Does anyone know why this would be happening? Sorry if I wasn't clear; there's so much code I wouldn't know where to start including it here. Thanks!
I am going to assume you are using MSVS based on the stdafx.h header name. When including static libraries, you not only have to include the needed header files, but you have to link with a static library file, i.e. a .lib file. My guess is that project X has access to that .lib file, while project Y doesn't.
Perhaps through properties->common properties->References and then "add new reference" to point to both your libraries.
Is your project Y, as well as Project X, A, B in the same solution? Adding those projects to the same solution as Y might help. I have only done this having a solution containing all the static libraries I want to include. In my case the paths were automatically (and correctly) set by MSVS. Though that likely requires adding the projects to the solution. (that would be using the method I mentioned above "properties->common properties->References" etc.).
If this is a .lib file from outside your project, you have to include it in "properties->Configuration Properties->Linker->Input->Additional dependencies", and make sure it's path is in "properties->Configuration Properties->Linker->General->Additional Library Directories"
Hope that helps

Lesson needed on how to work with files in different projects in C++

I have been able to work in the same project for sometime now, writing and successfully running c++ code. However, I discovered that I am still missing some essentials on how to export my .h files to another project and successfully use them in there.
I created a second project, project B to test the classes I have in project A.
visual c++: #include files from other projects in the same solution
I added the path of the header file in Project A into the Additional Include Directories(C\C++>general and Linker>general) section in the project configuration of Project B. I tried following the tutorials on this page http://msdn.microsoft.com/en-us/library/ms235636.aspx but I still end up with the error below
** LINK : fatal error LNK1104: cannot open file 'C:\Users\LaC\Projects\OSGB\Debug\OSGB.lib**
I would appreciate any help in understanding exactly how this is done so that in future, when I encounter this problem, I can know how to troubleshoot.
The code below is all I am working with.
IN PROJECT A
=============
//Utility.h
class Utility
{
private:
protected:
public:
Utility(void);
~Utility(void);
double square_root (const double);
};
//Utility.cpp
#include "StdAfx.h"
#include "Utility.h"
Utility::Utility(void)
{
//do nothing for now
}
Utility::~Utility(void)
{
//do nothing for now
}
double Utility::square_root (const double)
{
return 0;
}
IN PROJECT B
===============
#include "gtest/gtest.h"
#include "Utility.h"
TEST (SquareRootTest, PositiveNos) {
Utility u;
EXPECT_EQ (50.3321, u.square_root (2533.310224));
}
There are two (general) ways to include files into your project:
Make them a part of your project (adding them from the solution explorer) OR
Import them as a library (static or dynamic linking)
If you make them part of your project, then you have to add the header and the source files in order for the project to compile correctly. However, that's usually not what you want to do, as it defeats the purpose of having external libraries.
The second case is to use the external libraries, which requires that you:
Include the header files which are exported by the library in your C++ properties.
For static linking: you also have to include the *.lib file (the output of building the library) in the Linker properties.
OR
For dynamic linking: see tutorial.
So remember: there are two parts to building a C++ project- compiling and linking.
Compiler Errors:
If you get an error whose code starts with C* (e.g. C1083) and is related to problems header with the files, then check the Properties-> C/C++ -> General -> Additional Include Directories.
Linker Errors:
If you get an error whose code starts with LNK*, then check
Properties -> Linker -> General -> Additional Library Directories (make sure that this points to where the *.lib file is located)
AND
Properties -> Linker -> Input -> Additional Dependencies (make sure that the *.lib file is added here).
If you're dynamically linking, then check that you're correctly referencing the DLL.
So in your case, you have to determine if you're linking statically or dynamically and then make the appropriate references. So ware you getting those header files from a dynamically library or a static library?
When the linker emits unresolved external symbol for a symbol that lives in another library (DLL or shared library), this indicates that you need to link your app to that other library's .lib file. That is most likely what's happening here.
For more information see:
(MSDN) Walkthrough: Creating and Using a Dynamic Link Library (C++)

How to use functions from different C++ projects in Visual Studio 2010?

I would like to build two C++ projects in the same solution in Visual Studio 2010 that can interact with each other. I have created a solution under directory C:\Users\me\Desktop\SolutionDir. The two projects have been created respectively under C:\Users\me\Desktop\SolutionDir\FirstProject and C:\Users\me\Desktop\SolutionDir\SecondProject.
My first project contains two files, a header function.h and a cpp file function.cpp
function.h
#pragma once
void print_stuff();
function.cpp
#include "function.h"
#include <iostream>
void print_stuff() {
std::cout << "hello world" << std::endl;
}
My second project contains the main file main.cpp
main.cpp
#include "FirstProject\function.h"
#include <iostream>
int main(void) {
print_stuff();
int stop;
std::cin >> stop;
return 0;
}
I added the directory C:\Users\me\Desktop\SolutionDir\ in my SecondProject Configuration Properties > C/C++ > General > Additional Include Directories. I still get the classical error : error LNK2019: unresolved external symbol when calling the function print_stuff().
Any ideas ?
Try building the first project as a Static Library in Project Properties/Configuration Properties/General/Configuration Type.
Then in your project properties for the second project, you'll need to change two things:
In Linker/General, you might need to add to "Additional Library Directories" the folder where the first project's .lib is built.
In Linker/Input, you will need to add to Additional Dependencies the name of the .lib file like FirstProject.lib or whatever its name is.
Yes, you need to export the functions using _declspec(dllexport) and import them in the project that calls the functions with _declspec(dllimport).
This duality is usually achieved with a macro:
#pragma once
#ifdef FIRST_PROJECT_BUILD
#define IMPEXP _declspec(dllexport)
#else
#define IMPEXP _declspec(dllimport)
#endif
IMPEXP void print_stuff();
In the configuration of your first project, you add FIRST_PROJECT_BUILD to your preprocessor directives. That way, when you compile first project, you tell the compiler the function is to be exported. However, when you include the file in a different project, that doesn't have FIRST_PROJECT_BUILD defined, you tell the compiler the function is implemented in a different library and should be imported.
Also, besides adding the extra include paths, you need to add the generated .lib files from the projects implementing the functions to the Extra dependencies tab in the Liner settings of your project configuration.
You can include a realPath for you include directory !
Like for your FirstProject include "./../"
And the same include dir for your second Project like that you can move or copy your directory SolutionDir and it will always work !
For your unresolved linked you have to add the function.cpp and function.h in your First and Second Project
You can place it in SolutionDir!
Like that You always have two files for your first and second project instead of four !
Hope it helps !