How to reuse C++ classes from one project to another without copying - c++

I am facing the following problem:
I have a project which contains math classes (.h and .cpp files).
I want to use these classes in a different project (not int he same solution) but I can't.
In the new project I add a path to the include files of my math project. When I try to #include them it works and I can see my classes but upon trying to use them I get "Unresolved external". I haven't created a .dll or a .lib so I really don't know what's causing this.
If you have any suggestions, I`ll appreciate it.
Thank you very much in advance.

When I try to #include them it works and I can see my classes but
upon trying to use them I get "Unresolved external". I haven't created
a .dll or a .lib so I really don't know what's causing this.
That you have not created a library is precisely the reason why you get the error. The compilation units in your new project ("the *.cpp files") include the headers for your classes and make use of the class definitions, but the definitions of the members are missing.
For example, let's say you have a file called "c.h" in your old project:
#ifndef C_H
#define C_H
class C
{
public:
C();
void f();
};
#endif
Some *.cpp file in your new project includes the header and uses the class:
#include "somepath/oldproject/c.h"
void someFunction()
{
C c;
c.f();
}
This compiles fine, but it will cause linker errors, because the definitions of C::C and C::f will be missing.
Now, the clean solution to this is certainly not adding somepath/oldproject/c.cpp from your old project to your new project, although that would fix the linker error, but to employ a library-based approach. Turn your math classes into a library project, let's call it "Math Utils", which produces a *.lib file (as you seem to be on Windows), for example math-utils.lib. Add the library's include and release path to your global include and library paths. Then add the math-utils.lib file to the new project's linker dependencies.
And change the code in your new project to:
#include <math-utils/c.h>
void someFunction()
{
C c;
c.f();
}
Do the same thing in the old project! You will end up with three different projects. Two application projects and one library project, the former two depending on the latter.
Creating your own libraries for the first time can be a bit intimidating, but the benefits are worth the trouble.
See also The Linker Is not a Magical Program.

Related

Are includes in a .h of a DLL exported? And should they?

I have a huge c++ project in which several different units are built as DLL libraries. Now I have a library that is basic and shall be consumed by most of the other projects.
So lets say the DLL.h file has something like:
#include <vector>
#include "OtherClass.h"
I added the .lib path etc..., so my other project can use the DLL. In fact I have no errors on including the DLL on my "main" project.
Now my question is the include is that included in my main project when I do #include "DLL.h"?
My rational being that since I will use vector in almost 100% of the projects that consume this DLL, I might as well push the include to it and not have one in every single project that uses it. (not sure if this is a best or worst practice).
The problem right now is my main project does recognize the types in OtherClass.h but not the type vector. Might this be because I don't explicitly use vector in the DLL and just did the include?
The problem was not in the DLL linkage or dependency chaining. The fact is I had forgotten to include the statement:
using namespace std;
So when I tried in the main project to do
vector<int> someVector;
I got an error that said vector is not a template.
Adding the "using" line solved it.
Another way to solve it would be to use std::vector, but since it is code that is already written, I went with the other options.
Thanks #MadScienceDreams, your question actually led me to the answer! And indeed the includes in the dll are chained to the file using it in this case.

C++ projects - where to include sql class file?

I'm reasonably new to C++ but have just inherited a set of 20+ C++ solutions that work together to create an application suite. I have a class held in a singular .cpp file that can be used to connect and communicate with an SQL database, and I want to make all of the solutions be able to use this class.
I have put the sql.cpp file in a directory called "Shared" that already existed. But where in each project do I include the file? I have tried including it in the stdafx file but that caused endless compiler errors. I have tried including it in each individual .cpp file that uses it within the project but as soon as I include it in more than one I get "already defined in obj" errors. I have also tried creating a separate .h file to instantiate the class and including that, but it seems to not find the .cpp file as I get unresolved external errors.
I hope I have explained that well enough - could anyone shed some light on this subject?
Thanks!
You don't include the cpp file.
First, take the functions prototype and create header file
if your Sql.cpp code is
bool Open(char* name)
{
//do something
}
void Close(char* name)
{
//do something else
}
your Sql.h header should be:
(you put only functions you want to call from outside the file)
#pragma once
bool Open(char* name);
void Close(char* name);
Second, I assume you better make a library (static library is the simplest, but better a shared or DLL depending your OS) and link to it from all the projects need it.
you can use the object file as well as static library if it not depends on anything else.
EDIT:
on Windows DLL:
On windows Static lib
how to build static library in linux
how to build shared library in linux

Accessing functions from external files in class definition

I'm trying to access functions from another file for use inside my class definition:
// math.cpp
int Sum(int a, int b){
return (a + b);
}
// my_class.cpp
#include <math.cpp>
#include <my_class.h>
int ComputeSomething() {
...
return ::Sum(num1, num2);
}
Despite my best efforts, I can't get the compiler to spit out anything outside the likes of ::Sum has not been declared or Sum was not declared in this scope.
I'm trying to wrap my head around code organization in C++, any help appreciated.
It might be worth noting that I'm programming for Arduino.
To be able to access functions from a user-defined library, best divide that library into a .h (or .hpp) and a .cpp file. I understand you have actually done this, but tried various options – among them the inclusion of the .cpp file – for the sake of finding a solution.
Still, to ensure things work as expected, the declarations of functions and classes should go into the .h file, best protected by something like
#ifndef MY_H_FILE
#define MY_H_FILE
/* ..Declarations.. */
#endif
Then to include the .h file (I'll assume it's named my.h), either use
#include "my.h" // path relative to build directory
or
#include <my.h> // path relative to any of the include paths
The latter only works if my.h is found on an include path previously known to the compiler (e.g. what is specified using the -I command line option in GCC). The former works if the path to the .h file given is relative to the directory your are building from.
Finally, do not use a file name that can be confused with a system library (such as "math.h"), especially if you are using the <...> syntax, as the include path will definitely include the system library header files.
Have you followed the instructions given here?
User-created libraries as of version 0017 go in a subdirectory of your
default sketch directory. For example, on OSX, the new directory would
be ~/Documents/Arduino/libraries/. On Windows, it would be My
Documents\Arduino\libraries. To add your own library, create a new
directory in the libraries directory with the name of your library.
The folder should contain a C or C++ file with your code and a header
file with your function and variable declarations. It will then appear
in the Sketch | Import Library menu in the Arduino IDE.

Include <string> not found compile error in Xcode 4.2

I'm getting include not found compile error in XCode. I have an iOS app project that i use Objective-c and c++ as mix.
Initially, i created one .h file and one .cpp file in my ios project. Then, I renamed the .cpp file to .mm file.
Here is my .h file;
TestLog.h
#ifndef CalculatorDemo_TestLog_h
#define CalculatorDemo_TestLog_h
#include <string>
using namespace std;
class TestLog
{
private:
string logString;
public:
void Log(string logMessage);
};
#endif
TestLog.mm
#include "TestLog.h"
void TestLog::Log(string logMessage)
{
//this->logString->append(logMessage);
}
What am I missing? Do I need to add std c++ library to my targetS? Something related to Search Header Paths?
I just need to use string type.
Thanks much for in advance
select project -> build setting -> apple LLVM compiler 5.1 -> language
In Compile Sources As change to Objective-C++
There's a quirk in XCode. I noticed it in 7.3. Most projects recognize .mm files and the STL, while one project I had did not. The fix was that I had to click on the top-left project icon, then click Targets > Build Phases > Link Binary with Libraries > and add in AppKit.framework. Next, I had to click Targets > Build Settings > search on "Compile Sources", and set it to "Objective C++" on all possible columns. Then, do a Clean and then a Build from the Product menu. This compiled properly then. Then, go back to that Compile Sources again and set it back to "According to File Type" on all possible columns. Then, click Build from the Product menu again. At that point, it compiled properly and allowed me to utilize the "according to file type" option, which I like better.
Oh, and if doing Cocoa stuff, don't forget to add the following header in your files:
#import <Cocoa/Cocoa.h>
And if doing command line stuff, don't forget to add the following instead of the Cocoa header:
#import <Foundation/Foundation.h>
i believe you need to include the whole path to the library. similarly to say "foundation" & "uiview" frameworks.
#import <Foundation/Foundation.h>
or
#import <UIKit/UIKit.h>
and yes, make sure you add the library to your target.
So I was having this issue with the Cocoapods library Bypass and none of these solutions did anything. The problem was with a file which Cocoapods creates called an umbrella header. This is located in <POD_NAME>/Support Files/<POD_NAME>-umbrella.h. Delete it, and it should build just fine.
Now for the explanation of why this is necessary: the umbrella header is mixing both C++ and Objective-C code directly in a header which is a big no-no apparently and ends up completely breaking the C++ imports. By removing it (which seems to have no effect?) this conflicting import which Cocoapods unknowingly created will go away.
Ran into this with xcode 12.4 with a project that is objective-c, but where I need one C++ modul. Solution: wrap the contents of the .h file in:
#if defined __cplusplus
declarations
#endif
Apparently xcode is not good at detecting a mix of sources.
see Expected ; after top level declarator, error in xcode
This often happens when Xcode doesn't understand that a C++ header file you've imported into Objective-C is actually for C++ code.
So you can solve this problem by finding the Objective-C file that imports C++ code, and simply change its extension from .m to .mm

C++ header-implementation-header-implementation dependency chain

I'm trying to create simple C++ incremental-build tool with dependency resolver.
I've been confused about one problem with cpp build process.
Imagine we have a library consists several files:
// h1.h
void H1();
// s1.cpp
#include "h1.h"
#include "h2.h"
void H1(){ H2(); }
// h2.h
void H2();
// s2.cpp
#include "h2.h"
#include "h3.h"
void H2(){ /*some implementation*/ }
void H3(){ /*some implementation*/ }
// h3.h
void H3();
When in client code including h1.h
// app1.cpp
#include "h1.h"
int main()
{
H1();
return 0;
}
there is implicit dependency of s2.cpp implementation:
our_src -> h3 -> s1 -> h2 -> s2. So we need to link with two obj files:
g++ -o app1 app1.o s1.o s2.o
In contrast when h3.h included
// app2.cpp
#include "h3.h"
int main()
{
H3();
return 0;
}
there is only one source dependency:
our_src -> h3 -> s2
So when we include h3.h we need only s2.cpp compiled (in spite of s1.cpp -> h2.h inclusion):
g++ -o app2 app2.o s2.o
This is very simple example of the problem, in real projects surely we may have several hundreds files and chains of inefficient includes may contain much more files.
So my question is: Is there a way or instruments to find out which header inclusion could be omitted when we check dependencies (without CPP parsing)?
I would appreciate for any responce.
In the case you stated to see the implicit dependence on s2.cpp you need to parse the implementation module s1.cpp because only there you will find that the s1 module is using s2. So to the question "can I solve this problem without parsing .cpp files" the answer is clearly a no.
By the way as far as the language is concerned there is no difference between what you can put in an header file or in an implementation file. The #include directive doesn't work at the C++ level, it's just a textual macro function without any understanding of the language.
Moreover even parsing "just" C++ declarations is a true nightmare (the difficult part of C++ syntax are the declarations, not the statements/expressions).
May be you can use the result of gccxml that parses C++ files and returns an XML data structure that can be inspected.
This is not an easy problem. Just a couple of many things that make this difficult:
What if one header file is implemented in N>1 source files? For example, suppose class Foo is defined in foo.h but implemented in foo_cotr_dotr.cpp, foo_this_function.cpp, and foo_that_function.cpp.
What if the same capability is implemented in multiple source files? For example, suppose Foo::bar() has implementations in foo_bar_linux.cpp, foo_bar_osx.cpp, foo_bar_sunos.cpp. The implemention to be used depends on the target platform.
One easy solution is to build a shared or dynamic library and link against that library. Let the toolchain resolve those dependencies. Problem #1 disappears entirely, and problem #2 does too if you have a smart enough makefile.
If you insist on bucking this easy solution you are going to need to do something to resolve those dependencies yourself. You can eliminate the above problems (not an exhaustive list) by a project rule one header file == one source file. I have seen such a rule, but not nearly as often as I've seen a project rule that says one function == one source file.
You may have a look at how I implemented Wand. It uses a directive to add dependencies for individual source files. The documentation is not fully completed yet, but there are examples of Wand directives in the source code of Gabi.
Examples
Thread class include file
Thread.h needs thread.o at link time
#ifdef __WAND__
dependency[thread.o]
target[name[thread.h] type[include]]
#endif
Thread class implementation on windows (thread-win32.cpp)
This file should only be compiled when Windows is the target platform
#ifdef __WAND__
target[name[thread.o] type[object] platform[;Windows]]
#endif
Thread class implementation on GNU/Linux (thread-linux.cpp)
This file should only be compiled when GNU/Linux is the target platform. On GNU/Linux, the external library pthread is needed when linking.
#ifdef __WAND__
target
[
name[thread.o] type[object] platform[;GNU/Linux]
dependency[pthread;external]
]
#endif
Pros and cons
Pros
Wand can be extended to work for other programming languages
Wand will save all necessary data needed to successfully link a new program by just giving the command wand
The project file does not need to mention any dependencies since these are stored in the source files
Cons
Wand requires extra directives in each source file
The tool is not yet widely used by library writers