I'm trying to crosscompile some porject in eclipse, but I'm getting a error which is driven me crazy. It has to be with the inclusions and libraries headers, in the picture it can be seen the project tree.
PICTURE
The issue is that I cannot understand why I the path I'm using is wrong for the compilation, any advice?
Thanks in advance,
This is the TestUtils.cpp where the inclusion gives error
#include "TestUtils.h"
#include <ibrdtn-0.8.0/utils/Utils.h> //sucks
CPPUNIT_TEST_SUITE_REGISTRATION (TestUtils);
void TestUtils::setUp()
{
}
void TestUtils::tearDown()
{
}
void TestUtils::tokenizeTest()
{
using namespace dtn::utils;
CPPUNIT_ASSERT(Utils::tokenize(":", "").empty());
CPPUNIT_ASSERT(Utils::tokenize(":", "::").empty());
CPPUNIT_ASSERT_EQUAL((int)Utils::tokenize(":", ":a:test::", 2).size(), 2);
CPPUNIT_ASSERT_EQUAL((int)Utils::tokenize(":", ":a:test::b::", 2).size(), 3);
//TODO how should the added string in the last item look like? "b::" or ":b::" or "::b::"
CPPUNIT_ASSERT(Utils::tokenize(":", ":a:test::b::", 2)[2] == "b::");
CPPUNIT_ASSERT_EQUAL((int)Utils::tokenize(":", ": :", 1).size(), 1);
CPPUNIT_ASSERT_EQUAL((int)Utils::tokenize(":", ": :t e s t: ").size(), 3);
}
The error is this
/tests/utils/TestUtils.cpp:10:38: warning: ibrdtn-0.8.0/utils/Utils.h: No such file or directory
And the Utils.h which does not seem to exist is this
#ifndef UTILS_H_
#define UTILS_H_
#include "ibrdtn/data/Bundle.h"
#include "ibrdtn/data/CustodySignalBlock.h"
#include "ibrdtn/data/StatusReportBlock.h"
#include "ibrdtn/data/PayloadBlock.h"
namespace dtn
{
namespace utils
{
class Utils
{
public:
static void rtrim(std::string &str);
static void ltrim(std::string &str);
static void trim(std::string &str);
static vector<string> tokenize(std::string token, std::string data, size_t max = std::string::npos);
static double distance(double lat1, double lon1, double lat2, double lon2);
static void encapsule(dtn::data::Bundle &capsule, const std::list<dtn::data::Bundle> &bundles);
static void decapsule(const dtn::data::Bundle &capsule, std::list<dtn::data::Bundle> &bundles);
private:
static void encapsule(ibrcommon::BLOB::Reference &ref, const std::list<dtn::data::Bundle> &bundles);
static double toRad(double value);
static const double pi;
};
}
}
#endif /*UTILS_H_*/
First problem, since it is not part of your includes being referenced by Eclipse, then it should be surrounded by quotations "" and not <>.
Second, your inclusion path is incorrect. There is a ibrtn subfolder
for which you are not taking account. So, instead of having the main parent folder, the inclusion path should be #include "ibrdtn/utils/Utils.h"
Fix those two items and you should be in business.
Related
I've seen similar questions, but not quite like the predicament I find myself in. I'm working with someone else's code, and their structure is like this.
//db_manager.h
class db_manager
{
class error;
bool logError(error::def_enum::Value v, string msg);
bool read(int id);
}
//db_manager.cpp
#include db_manager.h
bool logError(error::def_enum::Value v, string msg)
{
return error::logError(v, msg);
}
bool read(int id)
{
//do db access stuff
return true;
}
//error.h
#include db_manager
class error
{
bool read(int id);
}
//error.cpp
#include error.h
bool read(int id)
{
return db_manager::read(id);
}
bool logError(error::def_enum::Value v, string msg)
{
//do error service stuff
}
This is a pretty obvious simplification, but hopefully it demonstrates the issue.
When I compile, I get a lot of incomplete type errors whenever error is used in db_manager.cpp, and I can't include the relevant header files from error into db_manager.cpp, because then I have to add it to db_managers cmake dependencies, which means I have to list it in package.xml, and then it gets upset from the circular dependency. How can I get around this? If I could use error's members in db_manager without making error a dependency, I'd be good, I think, but I just can't figure out how to do that. I've seen many other forward-declaration questions on here, but for all of them, the declared class usage isn't very deep. Here I'm using class members, not just declaring a class pointer like other questions.
I definitely could use help, I just don't see any logical way to do this without completely scrapping the error package and writing a new one.
Edit: also, I simplified this out, but maybe I shouldn't have. error and db_manager are in two separate packages.
First: Your example is very bad. Please provide a minimum working example. I understand what your problem is (circular dependency), but your example is not showing this Problem. This is something you have to solve on an architectural level. You can't solve this inside CMake.
Depending on the Code you have shown you don't need to include db_manager.h in error.h, since you are not using anything from db_manager during the declaration of class Error. You only need to include it inside error.cpp, since there you are using one static method from db_manager. That way you don't have any circular dependency.
I have added a minimum working example below which compiles without any errors.
error.h
#ifndef _ERROR_H_
#define _ERROR_H_
#include <string>
class Error
{
public:
enum def_enum{ Val1, Val2};
bool read(int id);
static bool logError(def_enum v, std::string msg);
};
#endif /* _ERROR_H_ */
error.cpp
#include "error.h"
#include "db_manager.h"
bool Error::read(int id)
{
return db_manager::read(id);
}
bool Error::logError(Error::def_enum v, std::string msg)
{
//do error service stuff
return true;
}
db_manager.h
#ifndef _DB_MANAGER_H_
#define _DB_MANAGER_H_
#include <string>
#include "error.h"
class db_manager
{
public:
static bool logError(Error::def_enum v, std::string msg);
static bool read(int id);
};
#endif /* _DB_MANAGER_H_ */
db_manager.cpp
#include "db_manager.h"
bool db_manager::logError(Error::def_enum v, std::string msg)
{
return Error::logError(v, msg);
}
bool db_manager::read(int id)
{
//do db access stuff
return true;
}
main.cpp
#include "db_manager.h"
#include "error.h"
int main(){
db_manager::read(1);
db_manager::logError(Error::Val1, "Test");
Error e;
e.read(2);
return 0;
}
CMakeLists.txt
project(db_manager)
add_executable(executable main.cpp db_manager.cpp error.cpp)
I'm doing functional testing on c code. Have include .c file in test .cpp file so far, everything works well. But I need to include the same .c file in another .cpp file where I do other unit tests. Then I get problems that is already defined. Because I already include it in the first file cpp.
If merge all the test methods into one cpp file then it works well. If keep all unit test in one file get to big handle so I need to split up diffrent files in same project it also create help functions for secure that functions get in capsules.
This not a normal LNK2005 because I can not declare the variable and functions in .h: as extern BOOL MyBool; and then assign to it in a .c or .cpp file. Because need include c file as I do unit test this function. Also I can't or should avoid do any changes .c.
I looking way to keep include of .c local not effect other files in same project.
source.h
#ifndef SOURCE_H_
#define SOURCE_H_
#include "../car.h"
enum INITIALMODE {
INITIALMODE_NOT_POSITIONING, // 0
INITIALMODE_NO_DRIVER_INPUT, // 1
INITIALMODE_POSITION_LOW_POSITION, // 2
INITIALMODE_POSITION_STANDARD_POSITION, // 3
INITIALMODE_POSITION_HIGH_POSITION // 4
};
void initMotor(void);
#endif
source.c
/* Compiler include files */
#pragma once
#include "positioning.h"
#include "api.h"
#include "drive.h"
#include "types.h"
static void updateTarget(void);
static SWord getMax(UWord Limit, UWord Aux);
static DWord getHeight(void);
static Bool isMode(void);
static Bool isExiting(void);
#define cMaxHeight 100 * Profile.s.Max /* m -> mm */
void initMotor(void)
{
// do something
}
static void updatePositioning(void)
{
// do something
}
Test files look like this, however, this is very scaled for making exemple small.
UnitTest.cpp and UnitTest2.cpp
#include "CppUnitTest.h"
#ifndef UNIT_TEST
#define UNIT_TEST
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace Test
{
extern "C" {
#include "../../Test/source.h"
#include "../../Test/source.c"
}
TEST_CLASS(UnitTest_1)
{
public:
TEST_METHOD(Test_1)
{
// Verify that the initial state is as expected.
initTest();
//Expected value
UWord Expected = 500
//Trigger to execute.
UWord Test = updatePositioning();
// Verify that the results are as expected.
Assert::AreEqual(Expected, Test);
}
};
}
#endif
You should never include a .C or .CPP file.
However, you can compile C code in C++. Here's an example based on the information you gave in your initial post.
YourCCode.h
#ifndef YourCCode_H
#define YourCCode_H
int FunctionToTest(int SomeParams);
int TestStaticFunctions(int SomeParam1, int SomeParam2);
#endif // YourCCode_H
YourCCode.c
#include "YourCCode.h"
static int SomeStaticFunction(int Param1, int Param2)
{
return Param1 + Param2; // that needs extensive testing, obviously.
}
int FunctionToTest(int SomeParams)
{
return SomeStaticFunction(SomeParams, 1);
}
int TestStaticFunctions(int SomeParam1, int SomeParam2)
{
return SomeStaticFunction(SomeParam1, SomeParam2);
}
UnitTest1.cpp
extern "C" {
#include "YourCCode.h"
}
bool TestFunction(int Value)
{
return (FunctionToTest(Value) == Value+1);
}
UnitTest2.cpp
extern "C" {
#include "YourCCode.h"
}
void AnotherTestFunction(int Val, int Val2)
{
int newValue = TestStaticFunctions(Val, Val2);
ASSERT(newValue == Val+Val2);
}
Then compile your CPP and C file.
After you clarified your intent, I realized you're trying to test static functions from another unit. Static function, by definition, are only available to other functions in the same translation unit. This is mostly use as a protection to prevent programmers to call some functions without knowing how to validate their inputs, know the call order, etc...
My best bet here is either you choose that your functions are not static and you can test them from outside your translation unit, or you implement the test functions inside the translation unit containing those static functions. I would recommend the latter as a translation unit should know (architecturally speaking) how to test their own features.
As a third solution, if you don't have any control over the content of the C file (but since you have that C file, I doubt it), you could have a proxy CPP file that includes the C file, and create a proxy call for each static call.
That is a ugly hack, though, and could break very easily if the C file ever gets updated, so I'm advising against it.
Here's a quick example :
YourCCode.h
#ifndef YourCCode_H
#define YourCCode_H
void SomeFunction(void);
#endif // YourCCode_H
YourCCode.c
#include "YourCCode.h"
static int AddSomething(int Param1, int Param2)
{
return Param1 + Param2;
}
static int SubtractSomething(int Param1, int Param2)
{
return Param1 - Param2;
}
void SomeFunction(void)
{
// code meant to be called externally.
}
ProxyTestCode.hpp
bool TestAddSomething(void);
bool TestSubtractSomething(void);
ProxyTestCode.cpp
extern "C" {
#include "YourCCode.h"
#include "YourCCode.c"
}
bool TestAddSomething(void)
{
return (AddSomething(2,2) == 4);
}
bool TestSubtractSomething(void)
{
return (AddSomething(2,2) == 0);
}
UnitTest1.cpp
#include "ProxyTestCode.hpp"
void TestAdd(void)
{
ASSERT(TestAddSomething());
}
UnitTest2.cpp
#include "ProxyTestCode.hpp"
void TestSubtract(void)
{
ASSERT(TestSubtractSomething());
}
If you do that, don't compile your C file in your project.
I have a problem with a following code:
#ifndef HEADER_H_
class SelectorBox{
public:
string selectorName;
map < string, string > attributeMap;
void setSelectorName(string name);
void setAttribute(string key, string value);
};
string trimTheString(string str); //trimming a string
#endif
//include libraries
#include "Header.h"
using namespace std;
int main()
{
vector <SelectorBox> vectorSelectBox;
SelectorBox *selectorBox;
//code
return 0;
}
#include "Header.h"
#include "main.cpp"
void SelectorBox::setSelectorName(string name) //setter
{
name = trimTheString(name);
selectorName = name;
}
void SelectorBox::setAttribute(string key, string value) //setter
{
key = trimTheString(key);
value = trimTheString(value);
attributeMap[key] = value;
}
When I compile a program, it shows many errors (specifically errors 4430 and 2061), but I believe that the main error is:
error C2011: 'SelectorBox' : 'class' type redefinition.
You must define HEADER_H_. You missed second line from below code.
#ifndef HEADER_H_
#define HEADER_H_
...
#endif
You are including the same header twice, first before main second after main, this causes a problem if you don't use proper include guards.
Your include guard is incomplete, so multiple includes of the same header will cause this error. The trick is to check if a header-specific preprocessor name is defined: If not, then define it, else skip the whole header.
The pattern to use is like this
#ifndef GUARD
#define GUARD
/// the actual header contents
#endif
but simply copying it into every header will cause another problem, because its lack of header specificity. The simplest way to find a good name is to derive it from the file name itself. In your case I'd name the header after the class SelectorBox defined in it, so SelectorBox.h would be a good name, and the include guards would look like this:
#ifndef SELECTORBOX_H
#define SELECTORBOX_H
class SelectorBox {
/// etc.
};
#endif
Using multiple headers with the same include guard is much worse than using no include guards at all.
I guess, you have 3 files:
Header.h
main.cpp
FileX.cpp (you didn't disclose the real name of mister X so far)
In main.cpp you are including Header.h, in FileX.cpp you are including Header.h and main.cpp. Let me show a simplified version of what happens here:
The contents of main.cpp gets transformed into
//include libraries
class SelectorBox{
public:
string selectorName;
map < string, string > attributeMap;
void setSelectorName(string name);
void setAttribute(string key, string value);
};
string trimTheString(string str); //trimming a string
using namespace std;
int main()
{
vector <SelectorBox> vectorSelectBox;
SelectorBox *selectorBox;
//code
return 0;
}
Assuming you included string and map and there is another using namespace std; somewhere before your class definition, this could compile without errors.
But now let's see what happens in FileX.cpp. Its contents gets transformed into the following, and I hope you'll see now what the compilers sees: there is more than one definition of the class SelectorBox:
class SelectorBox{
public:
string selectorName;
map < string, string > attributeMap;
void setSelectorName(string name);
void setAttribute(string key, string value);
};
string trimTheString(string str); //trimming a string
//include libraries
class SelectorBox{
public:
string selectorName;
map < string, string > attributeMap;
void setSelectorName(string name);
void setAttribute(string key, string value);
};
string trimTheString(string str); //trimming a string
using namespace std;
int main()
{
vector <SelectorBox> vectorSelectBox;
SelectorBox *selectorBox;
//code
return 0;
}
void SelectorBox::setSelectorName(string name) //setter
{
name = trimTheString(name);
selectorName = name;
}
void SelectorBox::setAttribute(string key, string value) //setter
{
key = trimTheString(key);
value = trimTheString(value);
attributeMap[key] = value;
}
... compilers use to call that a "redefinition".
Let say I've decleared this within MyTools.h
#ifndef _MYTOOLS_
#define _MYTOOLS_
typedef struct {
// const
double LN20;
double LN40;
// methods
double NoteToFrequency(int noteNumber);
} Tool;
extern const Tool tool;
#endif // !_MYTOOLS_
For every compilation unit, there is only a global/const/unique instance of Tool. Exactly what I want.
But now: how can I define it? In the .h i've only declared it. How can I define it in .cpp? Tried somethings like:
tool.LN20 = 1.34;
But of course it doesn't works. And the method's definition?
extern doesn't define any variable it just declares it. What you wan't to achieve can be done as below:
The link Global const object shared between compilation units explains how to do it with extern const
t.h file
#ifndef _MYTOOLS_
#define _MYTOOLS_
struct Tool {
// const
double LN20;
double LN40;
double NoteToFrequency(int noteNumber);
} ;
extern const Tool tool ;
#endif // !_MYTOOLS_
t1.cpp
#include "t.h"
#include <stdio.h>
void use_tool()
{
printf("%f\n",tool.LN20);
printf("%f\n",tool.LN40);
return;
}
t2.cpp
#include "t.h"
#include <stdio.h>
const Tool tool = {.LN20 = 20.0, .LN40 = 30.2};
double Tool::NoteToFrequency(int noteNumber)
{
return 12.0;
}
void use1_tool()
{
printf("%f\n",tool.LN20);
printf("%f\n",tool.LN40);
return;
}
int main()
{
void use_tool();
use_tool();
use1_tool();
return 0;
}
Hope this helps.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 years ago.
I am working on a directory watcher class for my project.Its .dll type project in c++.I am using Visual Studio 2013 as my IDE.
I followed these basic steps:
1.Created a new project of type dll and c++ language
2.Added the class and dllExport type declaration
3.Build the project
4.Create a new project of type console app
5.Add refernce to the dll project( the two projects are in different directories )
6.Point to the path of header file in Additional include files
But after writing some code that uses.When compiling i get following error
Error 1 error LNK2019: unresolved external symbol "public: __thiscall DirectoryWatcher::DirectoryWatcher(void)" (??0DirectoryWatcher##QAE#XZ) referenced in function "void __cdecl `dynamic initializer for 'watcher''(void)" (??__Ewatcher##YAXXZ) C:\Users\Karthik\documents\visual studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\Source.obj ConsoleApplication2*
But the Dll project build successfully
At the beginning I got error pointing to the destructor but after writing the implementation (empty just braces { }) in header itself.That error was replaced by this one pointing to the constructor
Hers the header file
#define _SCL_SECURE_NO_WARNINGS
#ifdef DIRECTORYWATCHER_EXPORTS
#define APITYPE __declspec(dllexport)
#else
#define APITYPE __declspec(dllimport)
#endif
#if defined(_WIN32)
#define PLATFORM_WINDOWS
#elif __APPLE__
#define PLATFORM_MAC
#elif __linux
#define PLATFORM_LINUX
#endif
//-------------------------------------------
// Code Begins Here
//---------------------------------
#ifndef DIRECTORY_WATCHER_H
#define DIRECTORY_WATCHER_H
#define USE_DIRENT
//------------------------
// Includes
//--------------
#include<vector>
#include<iostream>
#include<fstream>
#include<string>
#include<sys\stat.h>
#include <tchar.h>
#include<map>
#ifdef PLATFORM_WINDOWS
#include<Windows.h>
#endif
#ifdef USE_BOOST
#include<boost/filesystem.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/uuid/random_generator.hpp>
#include <boost/lexical_cast.hpp>
#endif
#ifdef USE_DIRENT
#include <dirent.h>
#endif
using namespace std;
//Meta File
template<typename T>
struct Meta
{
string Name,Path;
size_t GUID;
float Size;
int Type;
// Can be anything like list of name or list of animation files or list of folder with a folder
vector<T> MetaInfo;
};
//---------------------------------------------
// TYPE DEFS
//-------------------------------------
APITYPE typedef hash<string> HashFunction;
APITYPE typedef Meta<string> FOLDER_META;
struct ChildrenTree
{
vector<Meta<string>> Children;
};
struct DirectoryTree
{
string ParentPath;
//map<Children Name,Related Info>
map<string, FOLDER_META> Child;
};
struct Changed_Data
{
FOLDER_META Old;
FOLDER_META New;
};
//------------------------------------
//operators
//------------------------------------
#ifdef USE_DIRENT
class DirectoryWatcher
{
//-----------------Type Defs------------------------
//typedef Meta<string> FOLDER_META;
public:
//Varaibles
FOLDER_META defaultMeta;
Meta<DirectoryTree> TreeMeta;
// Default Constructor
DirectoryWatcher(void);
~DirectoryWatcher(void){} // Eror at first pointed to the destructor which was solved by defining it here its self
// Obtains a list of files and folders in a directory
APITYPE void GetList(const string&, vector<FOLDER_META>* ReturnValue ,FOLDER_META* ThisDireMeta);
// Searches and Returns the pathto the file
APITYPE bool FindFile(const string& Path
,const string& FileName // File Name
, string* Ret //Path Returned
);
//Update and check to see if a file as moved or added or changed
// Monitor(vector<FOLDER_META>* ChangedFiles,bool* FilesChanged -> return types);
APITYPE void Monitor(vector<Changed_Data>* ChangedFiles,bool* FilesChanged);
// Creates a GUID for a file
APITYPE size_t CreateGUID(const string& fileName);
//Export metadata
APITYPE void ExportMeta(const string& Path,FOLDER_META meta);
// Get the meta data
APITYPE void GetFolderMeta(const string& Path,Meta<string> * ReturnValue );
//InitalizeMethod
// False if path invalid
// true if path correct
APITYPE bool Init(const string& Path //Path to the Project folder (The folder to watch)
);
APITYPE bool Init(const string& Path //Path to the Project folder (The folder to watch)
,vector<FOLDER_META> * Returnmetas);
APITYPE void MakeDir(const string& path);
private:
string Project_Path;
DIR* dir = nullptr;
DIR* MainDir = nullptr;
struct dirent* ent = nullptr;
DIR* tempDir = nullptr;
DirectoryTree Tree;
HashFunction hashFunc;
//Dpeth Search
DirectoryTree UnVisited;
//-------------------------------------
// Windows Specifif cCode
//---------------------------------
HANDLE ChangeNotifications[2];
TCHAR lpDrive[4];
TCHAR lpFile[_MAX_FNAME];
TCHAR lpExt[_MAX_EXT];
DWORD Notifications;
// Private methods
APITYPE long GetFolderSize( const string& Path);
APITYPE bool CheckPathValid(const string& Path);
APITYPE void RefreshFiles(vector<Changed_Data>* ChangedFiles,const string& path,bool OnlyThisFolder);
APITYPE void RefreshTree(vector<Changed_Data>* ChangedFiles, const string& path);
APITYPE void CreateTree(const string& Path );
APITYPE void SaveTree();
APITYPE void LoadTree();
APITYPE bool AreChildEqual(const FOLDER_META& metaA,const FOLDER_META& metaB );
};
#endif
#endif // !DIRECTORY_WATCHER_H
*I Omitted the implementation part as it was very large but here is only the constructor *
DirectoryWatcher.cpp
DirectoryWatcher::DirectoryWatcher(void)
{
Project_Path = "";
dir = nullptr;
MainDir = nullptr;
ent = nullptr;
tempDir = nullptr;
}
The TestAplication
Source.cpp
#include<DirectoryWatcher.h>
using namespace std;
DirectoryWatcher watcher;
// omitted part of code
int main(int argv, char* argc)
{
string Path;
cout << "enterPath";
cin >> Path;
bool ISCahnged;
vector<FOLDER_META> metas,Returnvalues;
vector<Changed_Data> changedDatas;
watcher.Init(Path, &Returnvalues);
while (true)
{
ISCahnged = false;
watcher.Monitor(&changedDatas, &ISCahnged);
if (ISCahnged)
{
for each (Changed_Data var in changedDatas)
{
OutChangedData(var);
}
}
}
return 0;
}
Omitted few lines for smaller code
Can anyone be kind enough to help sort the problem
Thank you
You need to export the class from the dll. There is a very good answer over here: Exporting a C++ class from a DLL