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));
}
Related
EDIT: I'm not the only one having this issue, maybe it's VS https://github.com/google/googletest/issues/2628
I'm having trouble getting GMock setup correctly. I'm using Windows and CMake, and adding GMock to my existing project.
The code that I'm trying to run is:
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using ::testing::AnyNumber;
namespace ifac
{
class Foo
{
public:
virtual ~Foo() = default;
virtual void Bar(int i) = 0;
};
class FooMock : public Foo
{
public:
MOCK_METHOD1(Bar, void(int));
};
TEST(FooTest, BarCalled)
{
FooMock m;
EXPECT_CALL(m, Bar(1)).Times(AnyNumber());
m.Bar(1);
}
}
When it runs I get an error saying:
Exception thrown: read access violation. this was 0xFFFFFFFFFFFFFFFB.
The error is in the void Mutex::ThreadSafeLazyInit() of gtest-port.cc.
This seems to only happen if I set CMAKE_CXX_STANDARD to 17 too. I'm not really sure where to start with this, since I don't know a lot about C++, CMake or gtest/gmock.
Here's a stripped down version of the CMakeLists.txt files I have.
cmake_minimum_required (VERSION 3.8)
project ("TestingDemo")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
enable_testing()
add_subdirectory("googletest")
add_executable(Tests
"Main.cpp"
"Tests.cpp")
target_link_libraries(Tests PUBLIC gtest gtest_main gmock gmock_main)
add_test(RunTests Tests)
I am having trouble figuring out how to build out a modularized c++ app and getting everything to link up properly. Specifically, I can't get some tests to build because ultimately I get an undefined reference error based on a class method. (I am new to c++ and CMake so I'm probably doing a lot wrong, but I'm learning!) I have gone through other posts and all I can glean is that I'm potentially not linking properly.
Both OrderBook and Strategy build just fine. However, when I go to build StrategyTests and OrderBookTests I get an error:
[ 83%] Linking CXX executable StrategyTests.exe
../../OrderBook/libOrderBook.a(OrderBook.cpp.o): In function `orderbook::OrderBook::notify_strategies(std::shared_ptr<orderbook::Order> const&, bool)':
/cygdrive/d/Dropbox/My Documents/Programming/CLionProjects/TradingSystem/OrderBook/OrderBook.cpp:220: undefined reference to `HYSTRAT::Strategy::onBookUpdate(std::shared_ptr<Events::TOB> const&, std::shared_ptr<Events::OrderBookEvent> const&, bool)'
/cygdrive/d/Dropbox/My Documents/Programming/CLionProjects/TradingSystem/OrderBook/OrderBook.cpp:220:(.text+0x11c4): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `HYSTRAT::Strategy::onBookUpdate(std::shared_ptr<Events::TOB> const&, std::shared_ptr<Events::OrderBookEvent> const&, bool)'
collect2: error: ld returned 1 exit status
I've tried a number of different things including fiddling with CMakeLists and headers, but none seem to work. It's pretty clear I don't know the true meaning of "undefined reference". I suspect this is an easy fix, but I posted the project setup below in case it's not.
Here's my setup:
Clion and Cygwin on Windows 10
Project Tree
TradingSystem
|-CMakeLists.txt
|\OrderBook
|-|-CMakeLists.txt
|-|-OrderBook.h
|-|-OrderBook.cpp
|\Strategy
|-|-CMakeLists.txt
|-|-Strategy.h
|-|-Strategy.cpp
|\Tests
|-|-CMakeLists.txt
|-|\OrderBookTests
|-|-|-CMakeLists.txt
|-|-|\BoostTests
|-|-|-|-CMakeLists.txt
|-|-|-|-OrderBookBoostTests.cpp
|-|\StrategyTests
|-|-|-CMakeLists.txt
|-|-|-StrategyBoostTests.cpp
CMakes
#TradingSystem/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(TradingSystem)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES main.cpp)
add_executable(TradingSystem ${SOURCE_FILES} ${HEADER_FILES})
include_directories(OrderBook Strategy Events)
add_subdirectory(OrderBook)
add_subdirectory(Strategy)
add_subdirectory(Events)
add_subdirectory(Tests/OrderBookTests)
add_subdirectory(Tests/StrategyTests)
target_link_libraries(TradingSystem OrderBook Strategy)
-
#TradingSystem/OrderBook/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(OrderBook)
include_directories(/cygdrive/c/Program Files/boost/boost_1_66_0)
set(CMAKE_CXX_STANDARD 11)
set(HEADER_FILES OrderBook.h)
set(SOURCE_FILES OrderBook.cpp)
add_library(OrderBook STATIC ${SOURCE_FILES} ${HEADER_FILES})
-
#TradingSystem/Strategy/CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Strategy)
include_directories(/cygdrive/c/Program Files/boost/boost_1_66_0)
set(CMAKE_CXX_STANDARD 11)
set(HEADER_FILES Strategy.h)
set(SOURCE_FILES Strategy.cpp)
add_library(Strategy STATIC ${SOURCE_FILES} ${HEADER_FILES})
-
#TradingSystem/Tests/CMakeLists.txt
project(Tests)
add_subdirectory(OrderBookTests)
add_subdirectory(StrategyTests)
-
#TradingSystem/Tests/OrderBookTests/CMakeLists.txt
project(OrderBookTests)
add_subdirectory(BoostTests)
[EDIT]
#TradingSystem/Tests/OrderBookTests/BoostTests/CMakeLists.txt
add_executable(BoostTests OrderBookBoostTests.cpp)
enable_testing()
include_directories(/cygdrive/c/Program Files/boost_1_66_0)
set(BOOST_ROOT "C:/Program Files/boost_1_66_0/")
set(BOOST_LIBRARYDIR "C:/Program Files/boost_1_66_0/")
find_package(Boost 1.66.0)
find_package(Boost COMPONENTS unit_test_framework REQUIRED)
include_directories(${BOOSTROOT})
link_directories("${BOOSTROOT}")
target_include_directories(OrderBook PRIVATE ${BOOST_INCLUDE_DIRS})
# Original:
# target_link_libraries(BoostTests OrderBook)
# Changed to:
target_link_libraries(BoostTests Orderbook Strategy)
if(NOT Boost_FOUND)
message(FATAL_ERROR "Could not find boost!")
endif()
[EDIT]
#TradingSystem/Tests/StrategyTests/CMakeLists.txt
project(StrategyTests)
add_executable(StrategyTests StrategyBoostTests.cpp)
enable_testing()
include_directories(/cygdrive/c/Program Files/boost_1_66_0)
set(BOOST_ROOT "C:/Program Files/boost_1_66_0/")
set(BOOST_LIBRARYDIR "C:/Program Files/boost_1_66_0/")
find_package(Boost 1.66.0)
find_package(Boost COMPONENTS unit_test_framework REQUIRED)
include_directories(${BOOSTROOT})
link_directories("${BOOSTROOT}")
target_include_directories(Strategy PRIVATE ${BOOST_INCLUDE_DIRS})
# Original:
# target_link_libraries(StrategyTests Strategy OrderBook)
# Change to:
target_link_libraries(StrategyTests Orderbook Strategy)
if(NOT Boost_FOUND)
message(FATAL_ERROR "Could not find boost!")
endif()
The Src Files
#TradingSystem/OrderBook/OrderBook.h
#fndef TRADINGSYSTEM_ORDERBOOK_H
#define TRADINGSYSTEM_ORDERBOOK_H
#include <vector>
using std::vector;
#include "Strategy.h"
#include "Events.h"
namespace orderbook {
/////////////////////
// HIDDEN CODE
/////////////////////
class OrderBook {
private:
vector<HYSTRAT::Strategy> strategies_;
bool notify_strategies(const order_ptr& o, bool add_flag);;
Events::order_book_event_ptr create_order_book_event(const order_ptr& order);;
public:
/////////////////////////////
// CONSTRUTORS; DESTRUCTORS
/////////////////////////////
inline bool subscribe(HYSTRAT::Strategy& s) {
strategies_.push_back(s);
}
#endif //TRADINGSYSTEM_ORDERBOOK_H
-
#TradingSystem/OrderBook/OrderBook.cpp
#include "OrderBook.h"
#include "Events.h"
#include "Strategy.h"
using orderbook::OrderBook;
using HYSTRAT::Strategy;
bool orderbook::OrderBook::notify_strategies(const order_ptr& o, bool add_flag) {
try {
Events::order_book_event_ptr event = create_order_book_event(o);
Events::topOfBook_ptr tob = get_top_of_book();
for (HYSTRAT::Strategy& strategy : strategies_) {
strategy.onBookUpdate(tob, event, add_flag);
}
return true;
} catch (const std::exception& e) {
return false;
}
}
-
#TradingSystem/Strategy/Strategy.h
#ifndef TRADINGSYSTEM_STRATEGY_H
#define TRADINGSYSTEM_STRATEGY_H
#include "Events.h"
namespace HYSTRAT {
class Strategy {
public:
void onBookUpdate(const Events::topOfBook_ptr& tob, const Events::order_book_event_ptr& e, bool event_flag);;
};
}
#endif //TRADINGSYSTEM_STRATEGY_H
-
#TradingSystem/Strategy/Strategy.cpp
#include "OrderBook.h"
#include "Strategy.h"
#include "Events.h"
using namespace HYSTRAT;
void Strategy::onBookUpdate(const Events::topOfBook_ptr &tob, const Events::order_book_event_ptr &e, bool event_flag) {
if (tob->bidP >= tob->offerP) {
quantity_t order_size = std::min(tob->offerQ, tob->bidQ);
order_ptr buy_order(new Order(tob->offerP, order_size, BUY));
order_ptr sell_order(new Order(tob->bidP, order_size, SELL));
send_order(buy_order);
send_order(sell_order);
}
}
I think you are missing a few calls to "add_dependencies" in your CMakeLists.txt files. I think this particular problem might be solved by adding
add_dependencies(OrderBook Strategy)
to your Orderbooks CMakelists.txt
I'm testing my project using Catch2 as library. I followed every step in the Catch doc, but when I run the tests I get the following error:
CMakeFiles/tests.dir/tests/IntegerIntervalTest.cpp.o: in function "____C_A_T_C_H____T_E_S_T____0()":
/home/davide/cpp-project/tests/IntegerIntervalTest.cpp:8: undefined reference to "domain::IntegerAbstractInterval<int, int>::IntegerAbstractInterval(int, int)"
and this error repeates for every method call in the test "class".
CMakeLists:
PROJECT(cpp_project)
CMAKE_MINIMUM_REQUIRED(VERSION 3.5)
INCLUDE(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG(-std=c++14 COMPILER_SUPPORTS_CXX14)
IF (COMPILER_SUPPORTS_CXX14)
ADD_COMPILE_OPTIONS("-std=c++14")
ELSE ()
MESSAGE(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} has no C++14 support.")
ENDIF ()
set(BASE_SRCS src/Bound.cpp src/Bound.hpp src/Infinity.cpp src/Infinity.hpp src/AbstractInterval.cpp src/AbstractInterval.hpp
src/UndefinedOperationException.hpp src/IntegerAbstractInterval.cpp src/IntegerAbstractInterval.hpp src/FloatingPointAbstractInterval.cpp
src/FloatingPointAbstractInterval.hpp)
ADD_COMPILE_OPTIONS("-Wall" "-Wextra" "-Wpedantic" "-Werror" )
ADD_LIBRARY(cpp-project ${BASE_SRCS})
INCLUDE_DIRECTORIES(libs/variant/include)
set(EXECUTABLE_OUTPUT_PATH bin)
set(CATCH_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/catch)
add_library(Catch INTERFACE)
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
set(TEST_SRCS tests/InfinityTest.cpp tests/IntegerIntervalTest.cpp)
add_executable(tests ${BASE_SRCS} ${TEST_SRCS})
target_link_libraries(tests Catch)
and this is the test file IntegerIntervalTest.cpp:
#include "../src/IntegerAbstractInterval.hpp"
#include "../libs/catch2/catch.hpp"
using namespace domain;
TEST_CASE("Operations on IntegerInterval instances", "[IntegerAbstractInterval]") {
IntegerAbstractInterval<int, int> i(0,1);
IntegerAbstractInterval<Infinity, Infinity> ii(Infinity('-'), Infinity('+'));
IntegerAbstractInterval<Infinity, int> iii(Infinity('-'), 5);
IntegerAbstractInterval<int, Infinity> iv(0, Infinity('+'));
IntegerAbstractInterval<int, int> v(-1,1);
SECTION("Sum operations") {
auto res1 = i + v;
REQUIRE(res1.getLowerBound() == Bound(-1));
REQUIRE(res1.getUpperBound() == Bound(2));
}
}
I had the same problem and it was fixed by firstly defining the #define and then the #include:
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
A nice tutorial on setting up and using Catch2 is provided by JetBrains for CLion IDE.
This my project structure:
main
|
--src
|
--feed.h
--feed.cc
--other files
--CMakeLists2.txt
--test
|
--test.cpp
--CMakeLists3.txt
CMakeLists1.txt
CMakeLists1.txt
cmake_minimum_required (VERSION 2.8.11)
project (Feedparser)
set(CMAKE_MODULE_PATH cmake)
find_package(PTHREAD REQUIRED)
find_package(CURL REQUIRED)
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++14" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 ")
elseif(COMPILER_SUPPORTS_CXX0X)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x ")
else()
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()
add_subdirectory (src)
add_subdirectory (test)
CMakeLists2.txt
cmake_minimum_required (VERSION 2.8.11)
add_library (Feedparser news.h xml2json.hpp jsonxx.cc curler.cc feed.cc )
target_link_libraries(Feedparser pthread)
target_link_libraries(Feedparser curl)
install(TARGETS Feedparser
RUNTIME DESTINATION bin
LIBRARY DESTINATION lib
ARCHIVE DESTINATION /usr/lib)
install(FILES "feed.h" DESTINATION /usr/include )
target_include_directories (Feedparser PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
CMakeLists3.txt
cmake_minimum_required (VERSION 2.8.11)
add_executable(Feedtest test.cc)
target_link_libraries (Feedtest LINK_PUBLIC Feedparser)
Here is my Header file.
feed.h
#include "news.h"
#include "curler.cc"
#include "jsonxx.h"
#include "jsonxx.cc"
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <thread>
#include <stdio.h>
using namespace std;
using namespace jsonxx;
class feed{
map <string,string> info;
std::map<int, Object> items;
string url;
news News;
Object *item;
void strip_items();
public:
Object json;
feed(string url);
void create(string url){
this->url = url;
}
feed(){}
string get_topic(){
return info["title"];
}
bool fetch();
bool fetch_data();
bool parse();
string get_url(){
return url;
}
string get_item_title(int index){
return News.title[index];
}
string get_item_img(int index){
return News.image[index];
}
string get_item_link(int index){
return News.link[index];
}
int get_total(){
return News.num_item;
}
struct news get_news(){
return News;
}
};
Should I include feed.h in feed.cc and compile and how does the compiler directly link .h files with the .cxx files in archives?
How do i write a cmake script for installing this library?
Where is my mistake?
C++'s building process consists of 2 stages:
Compilation: The compiler runs on every source (.cc) file, generating an intermidiate binary.
Linking: The linker runs on every intermidiate binary, matching declarations with definitions.
Finally, it combines all of them to make the final binary.
With this in mind, you need to make sure the compiler doesn't come across something that it doesn't know about. That's why you include headers (.h).
The linker should be fed with everything the compiler creates.
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.