Ok, since I'm working on a private project using ROS Framework, my motivation was raised by the new C++14 auto lambda feature (see this link for a better explanation).
the problem I am facing is that ROS framework is sticking to the old days C++03 for it's compilation. So, how can I enable C++14 compilation support and how can I use the lambda functions ?
Here's a simple nodes for testing with the lambda function (in the subscriber node) :
publisher :
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <std_msgs/Int8.h>
#include <sstream>
int main(int argc, char **argv)
{
ros::init(argc, argv, "talker");
ros::NodeHandle n;
ros::Publisher string_pub = n.advertise<std_msgs::String>("chatter_string", 1000);
ros::Publisher int_pub = n.advertise<std_msgs::Int8>("chatter_int", 1000);
ros::Rate loop_rate(10);
int count = 0;
while (ros::ok())
{
std_msgs::String str_msg;
std::stringstream ss;
ss << "hello world ";
str_msg.data = ss.str();
std_msgs::Int8 int_msg;
int_msg.data = count;
string_pub.publish(str_msg);
int_pub.publish(int_msg);
ros::spinOnce();
loop_rate.sleep();
++count;
}
return 0;
}
subscriber :
#include <ros/ros.h>
#include <std_msgs/String.h>
#include <std_msgs/Int8.h>
//generic lambda to add two variables
auto func = [](auto input) { return input + input; };
void StringCallback(const std_msgs::String::ConstPtr& msg)
{
ROS_INFO("I heard: [%s]", func(msg->data).c_str());
}
void IntCallback(const std_msgs::Int8::ConstPtr& msg)
{
int result = msg->data;
ROS_INFO("I heard: [%d]", func(result));
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "listener");
ros::NodeHandle n;
ros::Subscriber string_sub = n.subscribe("chatter_string", 1000, StringCallback);
ros::Subscriber int_sub = n.subscribe("chatter_int", 1000, IntCallback);
ros::spin();
return 0;
}
CMakeLists :
cmake_minimum_required(VERSION 2.8.3)
project(tutocpp14)
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
)
catkin_package()
include_directories( ${catkin_INCLUDE_DIRS} include )
add_executable(listener src/listener.cpp)
add_executable(publisher src/publisher.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
target_link_libraries(publisher ${catkin_LIBRARIES})
Making the package after this configuration throw me the following error :
tutocpp14/src/listener.cpp:10:43: error: ‘func’ was not declared in this scope
ROS_INFO("I heard: [%s]", func(msg->data).c_str());
It turned out that I can add the C++14 to ROS for my package compilation. Although this is not advised for publishing the packages.
Use of C++11/C++14 features and filesystem/networking/etc... TS's (Technical Specifications) is allowed if they are checked for at configure time and equivalent functionality can be provided with the extra compiler features. Support for C++11 is now a compiler requirement, but the API of the packages included in desktop-full will not use any C++11-specific feature. External packages are encouraged to follow this guideline.
But, still that I am not intending to publish my work for now, so, I can get myself the permit to do so.
To get C++14 support for a ROS package, I have to set the -std=c++14 flag by adding the following lines in my CMakelists.txt file :
# check c++14 / c++0x
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX14)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX14)
set(CMAKE_CXX_FLAGS "-std=c++14")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "-std=c++0x")
else()
message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++14 support. Please use a different C++ compiler.")
endif()
this will check the existence of C++14 in the compiler and throw an error if not. Now, it works like a charm.
Hope that helps. Cheers.
Related
This is my C++ code:
#include "stdlib.h"
#include "stdio.h"
#include <iostream>
int main(int argc, char *argv[] ) {
int width, height;
unsigned char *rgba;
FILE *fp = fopen("/home/pic.tif", "rb");
if(!fp)
std::cout<<"failed"<<std::endl;
rgba = floadtiff(fp, &width, &height);
fclose(fp);
if(rgba == 0)
printf("TIFF file unreadable\n");
}
I am using this library by #MalcolmMcLean, and that's what my loadtiff.c is.I have compiled it using gcc and am trying to link that library.
This is my CMakeLists.txt:
cmake_minimum_required(VERSION 2.8.12.2)
project (test)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} cmake/)
add_executable(test tiffs.cpp)
target_link_libraries(test loadtiff)
and these are the errors I get when trying to make the program:
error: ‘floadtiff’ was not declared in this scope
Why can't I access this function, which is defined in loadtiff.c?
In tipps.cpp add:
extern "C" {
#include "loadtiff.h"
}
In CMakeLists.txt change to:
cmake_minimum_required(VERSION 2.8.12.2)
project(tiffs)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} cmake/)
add_library(loadtiff tiffloader/loadtiff.c)
target_include_directories(loadtiff PUBLIC tiffloader/loadtiff.h)
add_executable(tiffs tiffs.cpp)
target_link_libraries(tiffs loadtiff)
where "tiffloader/" is wherever you put the "loadtiff" files.
Do not name projects or targets after reserved words like "test", or you will get CMake warnings.
So you've got 2 problems.
1) your code is an abhorrent mixture of C and C++. For example, you're outputting text using C++
std::cout<<"failed"<<std::endl;
and C
printf("TIFF file unreadable\n");
Pick just one language and stick to it. Given it appears that floadtiff is expecting a FILE *, you'll probably be better off writing your code in C.
2) You're trying to use a library without telling the compiler anything about it. That's what header files are for. They tell the compiler you're using code from a different file and how the functions in that file are called. There should be a "loadtiff.h" file somewhere - you need to include that. That will contain definitions for the functions inside "loadtiff.c", such as floadtiff.
Without those definitions, your compiler has no idea if you're passing in the right number and/or type of parameters to those functions. It doesn't know what the return type of the function is or if it doesn't have one.
In C++ this information is especially important as you have function overloading, so it has to know exactly which function you're calling. In C, it's not quite so rigid and will make assumptions - which are often incorrect - about the function, but it will still warn you that it's done this.
If I use the following source
#include <cstdlib>
#include <cstdio>
#include <iostream>
extern "C" {
#include "loadtiff.h"
}
int main(int argc, char argv[] ) {
int width, height;
unsigned char* rgba;
FILE* fp = fopen("/home/user/pic.tif", "rb");
if(!fp)
std::cout << "failed" << std::endl;
rgba = floadtiff(fp, &width, &height);
fclose(fp);
if(rgba == 0)
printf("TIFF file unreadable\n");
return 0;
}
with the following CMakeLists.txt file under Visual Studio 14 and CMake 3.8.2
cmake_minimum_required(VERSION 2.8.12.2)
project (test)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} cmake/)
add_executable(test tiffs.cpp)
add_library(loadtiff STATIC loadtiff.c)
target_link_libraries(test loadtiff)
CMake generates a fully functional solution and Visual Studio is able to build it without errors.
Edit:
I assumed you have tiffs.cpp, loadtiff.c and loadtiff.h located in the same directory.
Here is the cmake file that i am using
cmake_minimum_required (VERSION 3.0)
project (midasd)
set (midas VERSION_MAJOR 0)
set (midas VERSION_MINOR 0)
set (midas VERSION_REVISION 1)
find_library(libconfig libconfig)
add_executable(midasd src/main.cpp)
target_link_libraries(midasd "${libconfig_LIBS}")
The problem i am facing is undefined reference for config_init. The main function is as follows
#include <libconfig.h>
int main(int argc, char *argv[])
{
midas::midasCtx *container = new midas::midasCtx(argc,argv);
config_t cfg;
config_init(&cfg);
return 0;
}
Where am i going wrong with CMAKE ?
Actually the libconfig is recognized as simply -lconfig not -llibconfigin linking argument. The CMakeLists.txt should contain
target_link_libraries(my_project config)
Source
This manual(https://hyperrealm.github.io/libconfig/libconfig_manual.html) says " To link with the library, specify ‘-lconfig++’ as an argument to the linker. "
So I fixed like following code and build was completed.
target_link_libraries(my_project config++)
I just installed CLion today on my new Linux environment and I decided to try to make a simple socket server. I eventually want to create a socket server in C++ (because I already made tons in C#, Java, Python, PHP, Node.js...).
I got the following code:
//
// Created by josh on 10-10-16.
//
#ifndef RANDOMPROGRAM_TEST_H
#define RANDOMPROGRAM_TEST_H
#include <iostream>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
using namespace boost::asio::ip;
class test {
private:
boost::asio::io_service io_service;
tcp::acceptor acceptor;
tcp::socket socket;
test() {
this->acceptor = tcp::acceptor(this->io_service, tcp::endpoint(tcp::v4(), 30000));
this->socket = tcp::socket(io_service);
acceptor.async_accept(this->socket, boost::bind(&this->handle_accept, this, this->socket, NULL));
}
void handle_accept(tcp::socket* client, const boost::system::error_code& error) {
}
};
#endif //RANDOMPROGRAM_TEST_H
In my main .cpp file (which gets called when the program is executed):
#include "test.h"
int main() {
test t();
return 0;
}
Finally, my CMakeLists.txt
cmake_minimum_required(VERSION 3.6)
project(Randomshitprogram)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
find_package(Boost 1.62.0 COMPONENTS system filesystem REQUIRED)
if(Boost_FOUND)
message(STATUS "Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
message(STATUS "Boost_LIBRARIES: ${Boost_LIBRARIES}")
message(STATUS "Boost_VERSION: ${Boost_VERSION}")
include_directories(${Boost_INCLUDE_DIRS})
endif()
set(SOURCE_FILES main.cpp test.h)
add_executable(Randomshitprogram ${SOURCE_FILES})
Now, when I try to execute the program, it gives the following error, together with possibly a ton of errors:
No matching function for call to ‘boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>::basic_socket_acceptor()’
The log:
http://pastebin.com/a09FvuTk
when I try to execute
you mean compile, right? That's a compile error, not a runtime one.
No matching function for call to 'boost::asio::basic_socket_acceptor<boost::asio::ip::tcp>::basic_socket_acceptor()'
The constructor for boost::asio::basic_socket_acceptor is documented here. There is no default constructor, which is what your compiler is telling you.
You're invoking (or trying to) the default constructor here:
test() /* here */ {
this->acceptor = tcp::acceptor(this->io_service, tcp::endpoint(tcp::v4(), 30000));
this->socket = tcp::socket(io_service);
acceptor.async_accept(this->socket, boost::bind(&this->handle_accept, this, this->socket, NULL));
}
where there is no initializer list. Any data members of test must be constructed before the body of your constructor.
Your constructor should look something like this:
test()
: acceptor(io_service, tcp::endpoint(tcp::v4(), 30000))
, socket(io_service)
{
acceptor.async_accept(socket, boost::bind(&this->handle_accept, this, this->socket, NULL));
}
CLion doesn't seem to recognize c++ tuples, although I can build and run my program from the terminal.
When trying to build, I only get "Build failed", while all the members of tuple are highlighted and I'm getting "Can't resolve namespace member tuple" (same with tie and make_tuple).
Here is my simple test:
#include<iostream>
#include<tuple>
std::tuple<int,int> testTuple();
int main(int argc, char** argv) {
int a, b;
std::tie(a,b) = testTuple();
std::cout<<a<<" "<<b;
return 0;
}
std::tuple<int,int> testTuple()
{
return std::make_tuple(0,1);
}
My CMakeLists.txt:
cmake_minimum_required(VERSION 2.8)
project(testTuple)
SET(CMAKE_CXX_COMPILER, /usr/bin/g++-4.8)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(CMAKE_BUILD_TYPE Debug)
set(SOURCE_FILES "src/main.cpp")
add_executable(simplification ${SOURCE_FILES})
For implementing such features as code-competition, jump to definitions and so on features CLion has it's own c++ parser.
So if your code compiled, but CLion show some kind of errors,
go and report bug to jetbrain (https://youtrack.jetbrains.com/issues/CPP)
I'm using boost 1.53.0, and have had no problems up to this point (and have used sockets, timers, containers, algorithm, all without trouple).
I love the idea of using boost exceptions, especially because of the line number and what not.
however, in my (super simple) code:
#include <iostream>
#include <fstream>
#include <boost/scoped_ptr.hpp>
#include <boost/exception/all.hpp>
struct my_error: virtual boost::exception, virtual std::exception { };
int main(int argc, char* argv[])
{
try
{
BOOST_THROW_EXCEPTION(my_error());
}
catch(...)
{
std::cout <<"fail";
}
}
Project generated with CMAKE (hopefully that's not screwing it up)
cmake_minimum_required (VERSION 2.8)
project(error_test)
IF(WIN32)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
set(Boost_NO_SYSTEM_PATHS FALSE)
ENDIF()
find_package(Boost COMPONENTS system date_time)
include_directories(${Boost_INCLUDE_DIRS}
)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME}
${Boost_LIBRARIES})
Instead of throwing, BOOST_THROW_EXCEPTION enters an infinite recursion!
The compiler even catches this, stating a compiler warning
warning C4717: 'boost::exception_detail::throw_exception_' : recursive on all control paths, function will cause runtime stack overflow.
and it just keeps hitting:
test.exe!boost::exception_detail::throw_exception_<my_error>(const my_error & x, const char * current_function, const char * file, int line) Line 84 + 0xd1 bytes C++
I am using visual studio 2010 (win 64). I built boost using the following command, if that helps:
.\b2 install --prefix=C:\devtools\boost_1_53_0 --toolset=msvc --build-type=complete --build-dir=C:\devtools\bin\boost_1_53_0 address-model=64 architecture=x86
EDIT Adding expanded macros:
looks like the macro expands to
::boost::exception_detail::throw_exception_(my_error(), __FUNCSIG__ ,"main.cpp",40);
which expands to
throw_exception_( E const & x, char const * current_function, char const * file, int line )
{
::boost::exception_detail::throw_exception_(set_info( set_info( set_info( enable_error_info(x), throw_function(current_function)), throw_file(file)), throw_line(line)), __FUNCSIG__ ,"C:\\devtools\\boost_1_53_0\\boost/throw_exception.hpp",91);
#line 92 "C:\devtools\boost_1_53_0\boost/throw_exception.hpp"
}
That's just plain weird. As you can easily check at https://svn.boost.org/svn/boost/tags/release/Boost_1_53_0/boost/throw_exception.hpp boost::exception::throw_exception_ is not not recursive at all.
The only way I can see such a thing happening is with evil macros. Please try putting this in your main file, before and after every include directive.
#if defined(throw_exception) || defined(throw_exception_)
#error Somebody set us up the bomb
#endif
OK, so it looks like for some reason
throw_exception_( E const & x, char const * current_function, char const * file, int line )
{
boost::throw_exception(
set_info(
set_info(
set_info(
enable_error_info(x),
throw_function(current_function)),
throw_file(file)),
throw_line(line)));
}
was changed to
throw_exception_( E const & x, char const * current_function, char const * file, int line )
{
BOOST_THROW_EXCEPTION(
set_info(
set_info(
set_info(
enable_error_info(x),
throw_function(current_function)),
throw_file(file)),
throw_line(line)));
}
in my code...so I must have broken my own boost build. Sorry about the wild goose chase! I voted to close this thread...