I am looking into JSON Serializer/ Deserializer c++ libraries and found the ThorSerializer to have all essential functoinalities and it keeps the variable names of key value pairs in the JSON Format as they are when serializing user defined classes, without replacing the keys with generic names, which is exactly what I need.
When I try to compile the basic example provided on the project's home page:
#include "ThorSerialize/Traits.h"
#include "ThorSerialize/JsonThor.h"
struct Shirt
{
int red;
int green;
int blue;
};
class TeamMember
{
std::string name;
int score;
int damage;
Shirt team;
public:
TeamMember(std::string const& name, int score, int damage, Shirt const& team)
: name(name)
, score(score)
, damage(damage)
, team(team)
{}
// Define the trait as a friend to get accesses to private
// Members.
friend class ThorsAnvil::Serialize::Traits<TeamMember>;
};
// Declare the traits.
// Specifying what members need to be serialized.
ThorsAnvil_MakeTrait(Shirt, red, green, blue);
ThorsAnvil_MakeTrait(TeamMember, name, score, damage, team);
int main()
{
using ThorsAnvil::Serialize::jsonExporter;
TeamMember mark("mark", 10, 5, Shirt{255,0,0});
// Use the export function to serialize
std::cout << jsonExporter(mark) << "\n";
}
I always end up receiving the following error output
/usr/bin/ld: CMakeFiles/test.dir/src/test.cpp.o: in function `main':
test.cpp:(.text+0xb7): undefined reference to `ThorsAnvil::Serialize::defaultPolymorphicMarker[abi:cxx11]'
/usr/bin/ld: CMakeFiles/test.dir/src/test.cpp.o: in function `ThorsAnvil::Serialize::JsonPrinter::~JsonPrinter()':
test.cpp:(.text._ZN10ThorsAnvil9Serialize11JsonPrinterD2Ev[_ZN10ThorsAnvil9Serialize11JsonPrinterD5Ev]+0x13): undefined reference to `vtable for ThorsAnvil::Serialize::JsonPrinter'
/usr/bin/ld: CMakeFiles/test.dir/src/test.cpp.o: in function `ThorsAnvil::Serialize::operator<<(std::ostream&, ThorsAnvil::Serialize::Exporter<ThorsAnvil::Serialize::Json, TeamMember> const&)':
test.cpp:(.text._ZN10ThorsAnvil9SerializelsERSoRKNS0_8ExporterINS0_4JsonE10TeamMemberEE[_ZN10ThorsAnvil9SerializelsERSoRKNS0_8ExporterINS0_4JsonE10TeamMemberEE]+0x65): undefined reference to `ThorsAnvil::Serialize::JsonPrinter::JsonPrinter(std::ostream&, ThorsAnvil::Serialize::PrinterInterface::PrinterConfig)'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/test.dir/build.make:103: test] Error 1
make[1]: *** [CMakeFiles/Makefile2:95: CMakeFiles/test.dir/all] Error 2
make: *** [Makefile:103: all] Error 2
I am using the header only version and my CMakeLists.txt looks as follows:
cmake_minimum_required(VERSION 3.4 FATAL_ERROR)
project("test")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Pistache REQUIRED)
include_directories(include)
add_executable(test src/test.cpp)
target_include_directories(test PUBLIC include include/ThorsSerializer)
To me it looks like the compiler can't find certain functions, although all of them are present in the respective header files and the namespaces. I checked for typos and similar but can't find the cause for my problems.
Does Anyone know what I might be doing wrong?
At the very beginning, you have to define a macro HEADER_ONLY by including a special header file named "ThorSerialize/SerializeConfig.h". This will unlock template definition functions located in .tpp file and remove "undefined definition" at compilation time.
Although, you may encounter other troubles because of "#endif" declared without its corresponding "#if". The quick fix I found, is to comment last line "#endif" of these following files:
ThorSerialize/CustomSerialization.source
ThorSerialize/Serialize.source
And finally, it will compile.
Related
I am using ros melodic on Ubuntu18.04 and C++14 and am trying to subscribe to a topic using a callback function in a Derived class. I know this is possible as a base class as seen in the 2.3.2 Class Methods section of the ros wiki, but I am trying to modify that for a derived class. I would like to be able to have multiple Scan_matching derived classes for different algorithms, and for main class to be able to select one. Here is what I have:
class Scan_Matching
{
public:
void get_transform(const sensor_msgs::PointCloud2ConstPtr& cloud_msg);
};
class ICP : public Scan_Matching
{
public:
void get_transform(const sensor_msgs::PointCloud2ConstPtr& cloud_msg);
};
int main(){
...
ScanMatching* scan_matching;
scan_matching = new ICP(...);
ros::Subscriber sub = nh.subscribe(topic, 100, &Scan_Matching::get_transform, scan_matching);
...
}
I am confident this is possible but I am not sure if I am implementing this correctly as I
get a linking error from catkin:
[ 14%] Linking CXX executable /home/mike/documents/autonomous_sim/devel/lib/mike_av_stack/localization
CMakeFiles/mike_av_stack_node.dir/scripts/localization/localization.cpp.o: In function `main':
localization.cpp:(.text.startup+0x718): undefined reference to `Scan_Matching::get_transform(boost::shared_ptr<sensor_msgs::PointCloud2_<std::allocator<void> > const> const&)'
collect2: error: ld returned 1 exit status
mike_av_stack/CMakeFiles/mike_av_stack_node.dir/build.make:392: recipe for target '/home/mike/documents/autonomous_sim/devel/lib/mike_av_stack/localization' failed
make[2]: *** [/home/mike/documents/autonomous_sim/devel/lib/mike_av_stack/localization] Error 1
CMakeFiles/Makefile2:2493: recipe for target 'mike_av_stack/CMakeFiles/mike_av_stack_node.dir/all' failed
make[1]: *** [mike_av_stack/CMakeFiles/mike_av_stack_node.dir/all] Error 2
Makefile:145: recipe for target 'all' failed
make: *** [all] Error 2
Invoking "make -j12 -l12" failed
To me this seems like the subscribe function is sending my get_transform function a parameter that is not the type
const sensor_msgs::PointCloud2ConstPtr& cloud_msg
(or in other words)
const boost::shared_ptr<sensor_msgs::PointCloud2 const>& cloud_msg
but instead the type
boost::shared_ptr<sensor_msgs::PointCloud2_std::allocator<void > const> const&
I tested this by trying the following code which compiles fine.
void callback(const boost::shared_ptr<sensor_msgs::PointCloud2 const>& cloud_msg){
}
int main(){
...
ros::Subscriber sub = nh.subscribe(topic, 100, callback);
...
}
I think it might be because of the derived class and I am calling the incorrect overloaded subscriber function. Can someone help me understand what I am doing wrong, and how to fix? Thank you
I'm getting an undefined referenced error, not knowing the reason why.
So I have 2 files which makes a static lib : keyboard_input.c, keyboard_input.h
Here's the content of the .h file:
#ifndef __MOD_KBINPUT__
#define __MOD_KBINPUT__
int kbInit();
int kbWait();
int kbTest();
#endif
And the CMakeLists.txt file looks like this:
FILE(
GLOB_RECURSE
sources
*.c
)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include/utils/kbreader")
ADD_LIBRARY(keyboardReader ${sources})
Compiling this lib gives some warnings:
src/utils/kbreader/keyboard_input.c: In function ‘kbInit’:
src/utils/kbreader/keyboard_input.c:13:14: warning: assignment from incompatible pointer type [enabled by default]
src/utils/kbreader/keyboard_input.c: In function ‘kbWait’:
src/utils/kbreader/keyboard_input.c:21:55: warning: passing argument 4 of ‘fread’ from incompatible pointer type [enabled by default]
/usr/include/stdio.h:708:15: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘struct FILE *’
Now, for my main executable (main.cpp):
#include <keyboard_input.h>
int main()
{
kbTest();
return 0;
}
Processed by the following CMakeLists.txt file:
include_directories("${PROJECT_SOURCE_DIR}/include/utils/kbreader")
file(
GLOB_RECURSE
srcs
*.cpp
)
add_executable(
PEM
${srcs}
)
target_link_libraries(PEM keyboardReader)
Ends up getting that error:
CMakeFiles/PEM.dir/main.cpp.o: In function `main':
main.cpp:(.text+0xb): undefined reference to `kbTest()'
collect2: ld returned 1 exit status
make[2]: *** [src/PEM/main2/PEM] Error 1
make[1]: *** [src/PEM/main2/CMakeFiles/PEM.dir/all] Error 2
The libkeyboardReader.a is created, and the kbTest() function doesn't do anything except
{return 0; }
If I set the definition of kbTest() in the header file, it works.
But there's something i don't get, when i type: make keyboardReader here is the output:
[ 73%] Building C object src/utils/kbreader/CMakeFiles/KeyboardReader.dir/keyboard_input.c.o
[Warning explained above]
Linking C static library ../../../lib/libKeyboardReader.a
Is there something wrong? Does the note error message makes my lib omit the keyboard_input.c file?
You're mixing C and C++ files. To make that work, you just have to tell the C++ compiler that it's calling a C function, by changing the header file like so:
#ifndef MOD_KBINPUT
#define MOD_KBINPUT
/* note I also fixed the macro so you aren't using a system-reserved name */
#if __cplusplus
/* this is the important part */
extern "C" {
#endif
int kbInit();
int kbWait();
int kbTest();
#if __cplusplus
}
#endif
#endif
Otherwise the C++ compiler assumes the function will be given a C++ internal name (which encodes all the type information in the signature, this is what lets the linker distinguish between overloaded functions) and then the linker doesn't find it.
i tryng to build a small example of Xerces with xerces c++ 3.1 and cmake, but i and only getting linkings problems.
This is my cmkelists.txt:
//============================================================================
project(ConfiguradorXerces)
cmake_minimum_required(VERSION 2.8)
include_directories (/home/ricardo/Desktop/librerias/xerces/xerces-c-3.1.1/src)
link_directories (/home/ricardo/Desktop/librerias/xerces/xerces-c-3.1.1/src/.libs)
link_directories (/home/ricardo/Desktop/librerias/xerces/xerces-c-3.1.1/src/)
set ( XercesLib xerces-c )
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${XercesLib})
//==============================================
//===============================================
#include <iostream>
#include <xercesc/util/PlatformUtils.hpp>
using namespace xercesc;
using namespace std;
int main()
{
try {
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch) {
// Do your failure processing here
return 1;
}
// Do your actual work with Xerces-C++ here.
XMLPlatformUtils::Terminate();
// Other terminations and cleanup.
return 0;
}
//==============================================
and this is my console output:
CMakeFiles/ConfiguradorXerces.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x25): undefined reference to `xercesc_3_1::XMLUni::fgXercescDefaultLocale'
main.cpp:(.text+0x2a): undefined reference to `xercesc_3_1::XMLPlatformUtils::Initialize(char const*, char const*, xercesc_3_1::PanicHandler*, xercesc_3_1::MemoryManager*)'
main.cpp:(.text+0x2f): undefined reference to `xercesc_3_1::XMLPlatformUtils::Terminate()'
CMakeFiles/ConfiguradorXerces.dir/main.cpp.o:(.gcc_except_table+0x10): undefined reference to `typeinfo for xercesc_3_1::XMLException'
collect2: error: ld returned 1 exit status
make[2]: *** [ConfiguradorXerces] Error 1
make[1]: *** [CMakeFiles/ConfiguradorXerces.dir/all] Error 2
make: *** [all] Error 2
16:28:55: The process "/usr/bin/make" exited with code 2.
Error while building/deploying project ConfiguradorXerces (target: Desktop)
When executing step 'Make'
//
i was thinking trhat my cmakeLsits.txt was not complete, there is an especial setup that it has to be done??
thx in advance
I am pretty sure that target_link_libraries() macro accepts a target as its first parameter:
target_link_libraries(<target> [item1 [item2 [...]]]
[[debug|optimized|general] <item>] ...)
And you have forgot to specify it. So instead of target_link_libraries(${XercesLib}), try target_link_libraries(${PROJECT_NAME} ${XercesLib}).
Hopefully, that solves it.
I'm getting an undefined referenced error, not knowing the reason why.
So I have 2 files which makes a static lib : keyboard_input.c, keyboard_input.h
Here's the content of the .h file:
#ifndef __MOD_KBINPUT__
#define __MOD_KBINPUT__
int kbInit();
int kbWait();
int kbTest();
#endif
And the CMakeLists.txt file looks like this:
FILE(
GLOB_RECURSE
sources
*.c
)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include/utils/kbreader")
ADD_LIBRARY(keyboardReader ${sources})
Compiling this lib gives some warnings:
src/utils/kbreader/keyboard_input.c: In function ‘kbInit’:
src/utils/kbreader/keyboard_input.c:13:14: warning: assignment from incompatible pointer type [enabled by default]
src/utils/kbreader/keyboard_input.c: In function ‘kbWait’:
src/utils/kbreader/keyboard_input.c:21:55: warning: passing argument 4 of ‘fread’ from incompatible pointer type [enabled by default]
/usr/include/stdio.h:708:15: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘struct FILE *’
Now, for my main executable (main.cpp):
#include <keyboard_input.h>
int main()
{
kbTest();
return 0;
}
Processed by the following CMakeLists.txt file:
include_directories("${PROJECT_SOURCE_DIR}/include/utils/kbreader")
file(
GLOB_RECURSE
srcs
*.cpp
)
add_executable(
PEM
${srcs}
)
target_link_libraries(PEM keyboardReader)
Ends up getting that error:
CMakeFiles/PEM.dir/main.cpp.o: In function `main':
main.cpp:(.text+0xb): undefined reference to `kbTest()'
collect2: ld returned 1 exit status
make[2]: *** [src/PEM/main2/PEM] Error 1
make[1]: *** [src/PEM/main2/CMakeFiles/PEM.dir/all] Error 2
The libkeyboardReader.a is created, and the kbTest() function doesn't do anything except
{return 0; }
If I set the definition of kbTest() in the header file, it works.
But there's something i don't get, when i type: make keyboardReader here is the output:
[ 73%] Building C object src/utils/kbreader/CMakeFiles/KeyboardReader.dir/keyboard_input.c.o
[Warning explained above]
Linking C static library ../../../lib/libKeyboardReader.a
Is there something wrong? Does the note error message makes my lib omit the keyboard_input.c file?
You're mixing C and C++ files. To make that work, you just have to tell the C++ compiler that it's calling a C function, by changing the header file like so:
#ifndef MOD_KBINPUT
#define MOD_KBINPUT
/* note I also fixed the macro so you aren't using a system-reserved name */
#if __cplusplus
/* this is the important part */
extern "C" {
#endif
int kbInit();
int kbWait();
int kbTest();
#if __cplusplus
}
#endif
#endif
Otherwise the C++ compiler assumes the function will be given a C++ internal name (which encodes all the type information in the signature, this is what lets the linker distinguish between overloaded functions) and then the linker doesn't find it.
I use extern variable for my application class so i can forward class function to glutDisplayFunction(funcPtr).
main.cpp:
#include "main.hpp"
int main(int argc, char** argv)
{
gApp = new GameApp();
return 0;
}
main.hpp:
#ifndef MAIN_HPP
#define MAIN_HPP
#include "GameApp.hpp"
#endif
GameApp.hpp:
#include <GL/gl.h>
#include <GL/freeglut.h>
class GameApp
{
public:
int running;
GameApp();
virtual ~GameApp();
void resize(int width, int height);
void init(int argc, char** argv, int width, int height);
void draw();
void update();
void key_input(unsigned char key, int x, int y);
};
extern GameApp *gApp;
void display_clb()
{
if (!gApp)
{
return;
}
gApp->draw();
}
This is the output:
g++ -o dist/Debug/GNU-Linux-x86/gravity build/Debug/GNU-Linux-x86/main.o build/Debug/GNU-Linux-x86/GBody.o build/Debug/GNU-Linux-x86/GameApp.o build/Debug/GNU-Linux-x86/GBodyList.o -lm -lGL -lglfw -lGLU -lglut
build/Debug/GNU-Linux-x86/main.o: In function `main':
/home/viktor/Documents/cpp/Gravity/main.cpp:6: undefined reference to `gApp'
/home/viktor/Documents/cpp/Gravity/main.cpp:7: undefined reference to `gApp'
/home/viktor/Documents/cpp/Gravity/GameApp.cpp:13: undefined reference to `gApp'
/home/viktor/Documents/cpp/Gravity/GameApp.cpp:18: undefined reference to `gApp'
build/Debug/GNU-Linux-x86/GameApp.o: In function `display_clb()':
/home/viktor/Documents/cpp/Gravity/GameApp.cpp:23: undefined reference to `gApp'
build/Debug/GNU-Linux-x86/GameApp.o:/home/viktor/Documents/cpp/Gravity/GameApp.cpp:28: more undefined references to `gApp' follow
collect2: ld returned 1 exit status
make[2]: *** [dist/Debug/GNU-Linux-x86/gravity] Error 1
make[2]: Leaving directory `/home/viktor/Documents/cpp/Gravity'
make[1]: *** [.build-conf] Error 2
make[1]: Leaving directory `/home/viktor/Documents/cpp/Gravity'
make: *** [.build-impl] Error 2
I expected gApp to be visible in my main.cpp and in GameApp class.
That's not a compile error, it is a link error. You variable declaration is visible just fine in main.cpp, but you haven't defined it anywhere - i.e. you don't allocate space for that variable anywhere.
You'll need one (and exactly one) C++ file that defines that variable. Possibly your main.cpp:
GameApp *gApp;
(You could initialize it too right there, but that is not necessary in this case.)
This tells the compiler there is a variable named gApp but it is defined somewhere else:
extern GameApp *gApp;
because that definition does not exist, the linker fails.
Add the following to another (and only one) source file:
GameApp *gApp;
With extern, you tell the compiler that the variable exists, but it is located somewhere else. The compiler believes you the variable exists, and
All you have to do is create the actual variable somewhere in the source. You can do this by simply adding something like GameApp *gApp; somewhere. For example in your cpp file.
Same as the previous answers from other guys, you announced the existence of gApp, but you did not actually provide it.
Add one more word: I suggest you put the definition of gApp in a "GameApp.cpp" file(not GameApp.hpp), and put the declaration of it in a "GameApp.h" file.