0%

Series

Guide

download source

1
2
wget https://github.com/schuhschuh/gflags/archive/v2.2.1.tar.gz
wget https://github.com/google/glog/archive/v0.3.5.tar.gz

gflags

1
2
3
4
cd gflags
mkdir build
cd build
cmake-gui ..

with options

BUILD_SHARED_LIBS ON 
INSTALL_SHARED_LIBS ON
INSTALL_STATIC_LIBS OFF
CMAKE_CONFIGURATION_TYPES Release
REGISTER_INSTALL_PREFIX OFF

#NAMESPACE google;gflags
NAMESPACE google

compile and install

1
2
make -j8
sudo make install

gflags-config.cmake

comes from caffe/cmake/Modules/FindGFlags.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# - Try to find GFLAGS
#
# The following variables are optionally searched for defaults
# GFLAGS_ROOT_DIR: Base directory where all GFLAGS components are found
#
# The following are set after configuration is done:
# GFLAGS_FOUND
# GFLAGS_INCLUDE_DIRS
# GFLAGS_LIBRARIES
# GFLAGS_LIBRARYRARY_DIRS

include(FindPackageHandleStandardArgs)

set(GFLAGS_ROOT_DIR "" CACHE PATH "Folder contains Gflags")

# We are testing only a couple of files in the include directories
if(WIN32)
find_path(GFLAGS_INCLUDE_DIR gflags/gflags.h
PATHS ${GFLAGS_ROOT_DIR}/src/windows)
else()
find_path(GFLAGS_INCLUDE_DIR gflags/gflags.h
PATHS ${GFLAGS_ROOT_DIR})
endif()

if(MSVC)
find_library(GFLAGS_LIBRARY_RELEASE
NAMES libgflags
PATHS ${GFLAGS_ROOT_DIR}
PATH_SUFFIXES Release)

find_library(GFLAGS_LIBRARY_DEBUG
NAMES libgflags-debug
PATHS ${GFLAGS_ROOT_DIR}
PATH_SUFFIXES Debug)

set(GFLAGS_LIBRARY optimized ${GFLAGS_LIBRARY_RELEASE} debug ${GFLAGS_LIBRARY_DEBUG})
else()
find_library(GFLAGS_LIBRARY gflags)
endif()

find_package_handle_standard_args(GFlags DEFAULT_MSG GFLAGS_INCLUDE_DIR GFLAGS_LIBRARY)


if(GFLAGS_FOUND)
set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR})
set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY})
message(STATUS "Found gflags (include: ${GFLAGS_INCLUDE_DIR}, library: ${GFLAGS_LIBRARY})")
mark_as_advanced(GFLAGS_LIBRARY_DEBUG GFLAGS_LIBRARY_RELEASE
GFLAGS_LIBRARY GFLAGS_INCLUDE_DIR GFLAGS_ROOT_DIR)
endif()

copy gflags-config.cmake to /usr/local/lib/cmake/gflags/

glog

1
2
3
4
cd glog
mkdir build
cd build
cmake-gui ..

with options

WITH_GFLAGS ON 
CMAKE_CONFIGURATION_TYPES Release

BUILD_SHARED_LIBS ON  # new by hand

compile and install

1
2
make -j8
sudo make install

glog-config.cmake

comes from caffe/cmake/Modules/FindGFlags.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# - Try to find Glog
#
# The following variables are optionally searched for defaults
# GLOG_ROOT_DIR: Base directory where all GLOG components are found
#
# The following are set after configuration is done:
# GLOG_FOUND
# GLOG_INCLUDE_DIRS
# GLOG_LIBRARIES
# GLOG_LIBRARYRARY_DIRS

include(FindPackageHandleStandardArgs)

set(GLOG_ROOT_DIR "" CACHE PATH "Folder contains Google glog")

if(WIN32)
find_path(GLOG_INCLUDE_DIR glog/logging.h
PATHS ${GLOG_ROOT_DIR}/src/windows)
else()
find_path(GLOG_INCLUDE_DIR glog/logging.h
PATHS ${GLOG_ROOT_DIR})
endif()

if(MSVC)
find_library(GLOG_LIBRARY_RELEASE libglog_static
PATHS ${GLOG_ROOT_DIR}
PATH_SUFFIXES Release)

find_library(GLOG_LIBRARY_DEBUG libglog_static
PATHS ${GLOG_ROOT_DIR}
PATH_SUFFIXES Debug)

set(GLOG_LIBRARY optimized ${GLOG_LIBRARY_RELEASE} debug ${GLOG_LIBRARY_DEBUG})
else()
find_library(GLOG_LIBRARY glog
PATHS ${GLOG_ROOT_DIR}
PATH_SUFFIXES lib lib64)
endif()

find_package_handle_standard_args(Glog DEFAULT_MSG GLOG_INCLUDE_DIR GLOG_LIBRARY)

if(GLOG_FOUND)
set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR})
set(GLOG_LIBRARIES ${GLOG_LIBRARY})
message(STATUS "Found glog (include: ${GLOG_INCLUDE_DIR}, library: ${GLOG_LIBRARY})")
mark_as_advanced(GLOG_ROOT_DIR GLOG_LIBRARY_RELEASE GLOG_LIBRARY_DEBUG
GLOG_LIBRARY GLOG_INCLUDE_DIR)
endif()

copy glog-config.cmake to /usr/local/lib/cmake/glog/

Example Code

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
cmake_minimum_required(VERSION 2.6)

project(glog_proj)

# Locate GTest
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})

find_package(GFLAGS REQUIRED)
include_directories(${GFLAGS_INCLUDE_DIRS})

find_package(GLOG REQUIRED)
include_directories(${GLOG_INCLUDE_DIRS})

# for windows
#add_definitions( -DGLOG_NO_ABBREVIATED_SEVERITIES )

MESSAGE( [Main] " GFLAGS_FOUND = ${GFLAGS_FOUND}")
MESSAGE( [Main] " GFLAGS_INCLUDE_DIRS = ${GFLAGS_INCLUDE_DIRS}")
MESSAGE( [Main] " GFLAGS_LIBRARIES = ${GFLAGS_LIBRARIES}")

MESSAGE( [Main] " GLOG_FOUND = ${GLOG_FOUND}")
MESSAGE( [Main] " GLOG_INCLUDE_DIRS = ${GLOG_INCLUDE_DIRS}")
MESSAGE( [Main] " GLOG_LIBRARIES = ${GLOG_LIBRARIES}")

add_executable(demo glog_main.cpp)
target_link_libraries (demo ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES})

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <gflags/gflags.h>
#include <glog/logging.h>

int main(int argc, char **argv)
{
/*
FLAGS_logtostderr = true;
FLAGS_alsologtostderr = true;
FLAGS_colorlogtostderr = true;
FLAGS_log_prefix = true;

FLAGS_logbufsecs = 0; //0 means realtime
FLAGS_max_log_size = 10; // MB
*/
google::InitGoogleLogging(argv[0]); // init google logging
google::SetLogDestination(google::GLOG_FATAL, "../log/log_fatal_");
google::SetLogDestination(google::GLOG_ERROR, "../log/log_error_");
google::SetLogDestination(google::GLOG_WARNING, "../log/log_warning_");
google::SetLogDestination(google::GLOG_INFO, "../log/log_info_");

LOG(INFO) << "Hello GLOG";

return 0;
}

Reference

History

  • 20180223: created.

Series

Guide

apt-get

install by apt-get, but we can not use find_package(Poco) because no /usr/local/lib/cmake/Poco/PocoConfig.cmake installed.

1
sudo apt-get install libpoco-doc libpoco-dev

compile from source

1
2
3
4
5
6
7
8
9
10
11
12
13
wget https://pocoproject.org/releases/poco-1.8.1/poco-1.8.1.tar.gz

#Install dependences
sudo apt-get install openssl libssl-dev
sudo apt-get install libiodbc2 libiodbc2-dev
sudo apt-get install libmysqlclient-dev

cd poco-1.8.1
#sudo ./configure --omit=Data/ODBC,Data/MySQL --no-tests --no-samples --shared
cd build
cmake-gui ..
sudo make -j8
sudo make install

OK. we install headers to /usr/local/include/Poco and libraries to /usr/local/lib/

1
2
3
4
$ ls /usr/local/libPoco*.so 

/usr/local/lib/libPocoFoundation.so /usr/local/lib/libPocoNet.so /usr/local/lib/libPocoXML.so
/usr/local/lib/libPocoJSON.so /usr/local/lib/libPocoUtil.so

we install cmake files to /usr/local/lib/cmake/Poco

1
2
3
4
5
6
7
8
9
10
$ ls /usr/local/lib/cmake/Poco

PocoConfig.cmake PocoJSONTargets.cmake PocoUtilTargets.cmake
PocoConfigVersion.cmake PocoJSONTargets-release.cmake PocoUtilTargets-release.cmake
PocoFoundationConfig.cmake PocoNetConfig.cmake PocoXMLConfig.cmake
PocoFoundationConfigVersion.cmake PocoNetConfigVersion.cmake PocoXMLConfigVersion.cmake
PocoFoundationTargets.cmake PocoNetTargets.cmake PocoXMLTargets.cmake
PocoFoundationTargets-release.cmake PocoNetTargets-release.cmake PocoXMLTargets-release.cmake
PocoJSONConfig.cmake PocoUtilConfig.cmake
PocoJSONConfigVersion.cmake PocoUtilConfigVersion.cmake

Example

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
cmake_minimum_required (VERSION 2.6)

project (event_demo)
enable_language(C)
enable_language(CXX)

# Always include the source and build directories in the include path.
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# Set the output folder where your program will be created
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})

# Find Poco package 1.8.1
find_package(Poco REQUIRED COMPONENTS Foundation Util Net XML JSON)

# no Poco_INCLUDE_DIRS, we have to set by hand
if(MSVC) # WIN32
SET(Poco_INCLUDE_DIRS "C:/Program Files/Poco/include")
else()
SET(Poco_INCLUDE_DIRS "/usr/local/include/Poco")
endif(MSVC)

MESSAGE( [Main] " Poco_INCLUDE_DIRS = ${Poco_INCLUDE_DIRS}")
MESSAGE( [Main] " Poco_LIBRARIES = ${Poco_LIBRARIES}")

# The following folder will be included
include_directories(
${MY_SRC_INCLUDE}
${Poco_INCLUDE_DIRS}
)

link_directories(${CMAKE_BINARY_DIR})

add_executable(event_demo event_demo.cpp)
target_link_libraries(event_demo ${Poco_LIBRARIES})

Reference

History

  • 20180222: created.

Guide

install VeloView

download VeloView and install.

For “sensor streaming” (live display of sensor data) it is important to change the network settings of the Ethernet adapter connected to the sensor from automatic IP address to manual IP address selection and choose:

Notes from VeloView github

  • VLP-16 / HDL-32E
    IP address: 192.168.1.77 (77 as example, any number except 201 works)
    Gateway: 255.255.255.0

  • HDL-64E
    IP address: 192.168.3.77 (77 as example, any number except 43 works)
    Gateway: 192.168.3.255

In order for sensor streaming to work properly, it is important to disable firewall restrictions for the Ethernet port. Disable the firewall completely for the ethernet device connected to the sensor or explicitly allow data from that Ethernet port of (including both public and private networks).

config guide

Setting up your computer to communicate with the sensor

  • Connect the computer to the interface box with an Ethernet Cable.
  • Apply power to the sensor.
  • For now, disable the WiFI connection on your computer.
  • Configure your computer’s IP address on its Ethernet port to manual mode.
  • Set your computer’s IP address to 192.168.1.77 (“77” can be any number except 0, 255, or 201)
  • Set the subnet mask to 255.255.255.0
  • Pull up the sensor’s webserver interface by typing the sensor’s network address, 192.168.1.201, into the address bar in your web browser

steps

windows ip config

  1. set computer IP address on its Ethernet port to to manual mode with ip=192.168.1.77 (77 can be any number except 0,255,201),gateway=192.168.1.1,mask=255.255.255.0

  2. check by ifconfig

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $ ifconfig

    以太网适配器 以太网:

    连接特定的 DNS 后缀 . . . . . . . :
    本地链接 IPv6 地址. . . . . . . . : fe80::9164:9f68:3c08:8493%17
    IPv4 地址 . . . . . . . . . . . . : 192.168.1.77
    子网掩码 . . . . . . . . . . . . : 255.255.255.0
    默认网关. . . . . . . . . . . . . : 192.168.1.1

    无线局域网适配器 WLAN:

    连接特定的 DNS 后缀 . . . . . . . :
    本地链接 IPv6 地址. . . . . . . . : fe80::b13c:895a:8b08:5ec2%6
    IPv4 地址 . . . . . . . . . . . . : 192.168.0.130
    子网掩码 . . . . . . . . . . . . : 255.255.255.0
    默认网关. . . . . . . . . . . . . : 192.168.0.1

ubuntu ip config

  1. set computer IP address on eth0 with ip=192.168.1.77 (77 can be any number except 0,255,201),gateway=192.168.1.1,mask=255.255.255.0

  2. edit network interfaces /etc/network/interfaces

    1
    2
    3
    4
    5
    6
    7
    8
    auto lo
    iface lo inet loopback

    auto eth0
    iface eth0 inet static
    address 192.168.1.77
    netmask 255.255.255.0
    gateway 192.168.1.1
  3. reboot

    1
    $ sudo reboot now
  4. check eth0

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    $ sudo ifconfig

    eth0 Link encap:Ethernet HWaddr 80:fa:5b:47:92:8a
    inet addr:192.168.1.77 Bcast:192.168.1.255 Mask:255.255.255.0
    UP BROADCAST MULTICAST MTU:1500 Metric:1
    RX packets:0 errors:0 dropped:0 overruns:0 frame:0
    TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

    lo Link encap:Local Loopback
    inet addr:127.0.0.1 Mask:255.0.0.0
    inet6 addr: ::1/128 Scope:Host
    UP LOOPBACK RUNNING MTU:65536 Metric:1
    RX packets:4640 errors:0 dropped:0 overruns:0 frame:0
    TX packets:4640 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:865530 (865.5 KB) TX bytes:865530 (865.5 KB)

    wlan0 Link encap:Ethernet HWaddr b0:35:9f:53:68:c6
    inet addr:192.168.0.130 Bcast:192.168.0.255 Mask:255.255.255.0
    inet6 addr: fe80::a3d7:e190:6fb3:133/64 Scope:Link
    UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
    RX packets:6536 errors:0 dropped:0 overruns:0 frame:0
    TX packets:380 errors:0 dropped:0 overruns:0 carrier:0
    collisions:0 txqueuelen:1000
    RX bytes:581427 (581.4 KB) TX bytes:46439 (46.4 KB)
  5. Establish communication with the webserver GUI with Default IP: 192.168.1.201 on chrome.

    • for windows:
      vlp16 web user interface for windows

    • for ubuntu
      vlp16 web user interface for ubuntu

we use data port 2368 in program.

  1. View vlp16 by VeloView

VeloView for vlp16

VelodyneCapture Example

We can get VelodyneCapture class from VelodyneCapture.h

  • HDLGrabber: This Grabber for HDL-64E/HDL-32E.
  • VLPGrabber: This Grabber for VLP-16.

In this article using Velodyne grabber that has implemented in PCL.
It returns coordinated Point Cloud data. You don’t need to convert coordinates yourself.

Reference

History

  • 20180211: created.
  • 20180222: add ubuntu velodyne ip config.

Packages

Boost

1
sudo apt-get install libboost-all-dev

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Boost
if(MSVC)
# use static boost on windows
set(Boost_USE_STATIC_LIBS ON)
else()
# use release boost on linux
set(Boost_USE_RELEASE_LIBS ON)
endif(MSVC)

set(Boost_USE_MULTITHREAD ON)
# Find Boost package 1.66.0
find_package(Boost REQUIRED COMPONENTS serialization date_time system filesystem thread timer)

include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(demo ${Boost_LIBRARIES})

GTest

1
git clone https://github.com/google/googletest.git

install to C:\Program Files\gtest on windows.

1
2
3
4
5
6
7
8
9
10
11
12
if(MSVC) 
SET(GTEST_ROOT "C:/Program Files/gtest")
else()
# BOOST_THREAD_LIBRARY /usr/lib/x86_64-linux-gnu/libpthread.so
MESSAGE( [Main] " BOOST_THREAD_LIBRARY = ${BOOST_THREAD_LIBRARY}")
endif(MSVC)

find_package(GTest REQUIRED) # GTest 1.8.0

find_package(GTest REQUIRED) # GTest 1.8.0
include_directories(${GTEST_INCLUDE_DIRS})
target_link_libraries(demo ${GTEST_LIBRARIES} ${BOOST_THREAD_LIBRARY})

gflags+glog

1
2
wget https://github.com/schuhschuh/gflags/archive/v2.2.1.tar.gz
wget https://github.com/google/glog/archive/v0.3.5.tar.gz

for find_package(GFLAGS REQUIRED) we copy user-defined gflags-config.cmake from caffe project to /usr/local/lib/cmake/gflags
for find_package(GLOG REQUIRED) we copy user-defined glog-config.cmake from caffe project to /usr/local/lib/cmake/glog
see compile glog and glags on ubuntu 16.04

1
2
3
4
5
6
7
8
9
10
11
find_package(GFLAGS REQUIRED) 
include_directories(${GFLAGS_INCLUDE_DIRS})

find_package(GLOG REQUIRED)
include_directories(${GLOG_INCLUDE_DIRS})

# for windows
#add_definitions( -DGLOG_NO_ABBREVIATED_SEVERITIES )

add_executable(demo glog_main.cpp)
target_link_libraries (demo ${GLOG_LIBRARIES} ${GFLAGS_LIBRARIES})

mysqlconcpp

1
2
sudo apt-cache search libmysqlcppconn
sudo apt-get -y install libmysqlcppconn-dev libmysqlcppconn7v5

for find_package(MYSQLCPPCONN REQUIRED) we copy user-defined mysqlcppconn-config.cmake to /usr/lib/cmake/mysqlcppconn

1
2
3
4
find_package(MYSQLCPPCONN REQUIRED)

include_directories(${MYSQLCPPCONN_INCLUDE_DIRS})
target_link_libraries (demo ${MYSQLCPPCONN_LIBRARIES})

libjpegturbo

1
git clone https://github.com/libjpeg-turbo/libjpeg-turbo.git

for find_package(LIBJPEGTURBO REQUIRED) we copy user-defined libjpegturbo-config.cmake to /usr/lib/cmake/libjpegturbo

1
2
3
find_package(LIBJPEGTURBO REQUIRED)
include_directories(${LIBJPEGTURBO_INCLUDE_DIRS})
target_link_libraries (example_jpeg ${LIBJPEGTURBO_LIBRARIES})

Poco

1
2
wget https://pocoproject.org/releases/poco-1.8.1/poco-1.8.1.zip
wget https://pocoproject.org/releases/poco-1.8.1/poco-1.8.1.tar.gz

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
find_package(Poco REQUIRED COMPONENTS Foundation Util Net XML JSON)

# no Poco_INCLUDE_DIRS, we have to set by hand
if(MSVC) # WIN32
SET(Poco_INCLUDE_DIRS "C:/Program Files/Poco/include")
else()
SET(Poco_INCLUDE_DIRS "/usr/local/include/Poco")
endif(MSVC)

MESSAGE( [Main] " Poco_INCLUDE_DIRS = ${Poco_INCLUDE_DIRS}")
MESSAGE( [Main] " Poco_LIBRARIES = ${Poco_LIBRARIES}")

include_directories(${Poco_INCLUDE_DIRS} )
target_link_libraries(demo ${Poco_LIBRARIES})

OpenCV

1
2
3
4
find_package(OpenCV REQUIRED COMPONENTS core highgui imgproc features2d calib3d) 

include_directories(${OpenCV_INCLUDE_DIRS})
target_link_libraries(demo ${OpenCV_LIBS})

QT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)

# Find the QtWidgets library
find_package(Qt5Core)
find_package(Qt5Widgets)
find_package(Qt5Gui)
find_package(Qt5OpenGL)
find_package(Qt5Xml)

# cpp files
aux_source_directory(. SRC_LIST)
# ui files
qt5_wrap_ui(ui_FILES mainwindow.ui)
# resource files
qt5_add_resources(qrc_FILES resource.qrc)

message( [Main] ${SRC_LIST} ) # ./main.cpp./mainwindow.cpp
message( [Main] ${ui_FILES} ) # build/ui_mainwindow.h
message( [Main] ${qrc_FILES} )# build/qrc_resource.cpp

# Tell CMake to create the helloworld executable
add_executable(${PROJECT_NAME} ${SRC_LIST} ${ui_FILES} ${qrc_FILES})

qt5_use_modules(${PROJECT_NAME} Core Widgets OpenGL Xml Gui)

VTK

1
2
3
4
5
6
find_package(VTK 8.1 REQUIRED)
include(${VTK_USE_FILE})

add_executable(CylinderRenderingProperties MACOSX_BUNDLE CylinderRenderingProperties.cxx )

target_link_libraries(CylinderRenderingProperties ${VTK_LIBRARIES})

PCL

1
2
3
4
5
6
7
8
find_package(PCL 1.8.1 REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (cloud_viewer cloud_viewer.cpp)
target_link_libraries (cloud_viewer ${PCL_LIBRARIES})

or with components

1
2
3
4
5
6
7
8
find_package(PCL 1.8.1 REQUIRED COMPONENTS common io filters visualization)

target_link_libraries(cloud_viewer
${PCL_COMMON_LIBRARIES}
${PCL_IO_LIBRARIES}
${PCL_FILTERS_LIBRARIES}
${PCL_VISUALIZATION_LIBRARIES}
)

User-defined cmake

gflags-config.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
set(GFLAGS_FOUND TRUE) # auto 
set(GFLAGS_VERSION 2.2.0)
set(GFLAGS_ROOT_DIR "C:/car_libs/gflags")

find_path(GFLAGS_INCLUDE_DIR NAMES gflags/gflags.h PATHS "${GFLAGS_ROOT_DIR}/include")
mark_as_advanced(GFLAGS_INCLUDE_DIR) # show entry in cmake-gui

find_library(GFLAGS_LIBRARY NAMES gflags.lib PATHS "${GFLAGS_ROOT_DIR}/lib")
mark_as_advanced(GFLAGS_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR} )
set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY} )

message( "gflags-config.cmake " ${GFLAGS_ROOT_DIR})

glog-config.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
set(GLOG_FOUND TRUE) # auto 
set(GLOG_VERSION 0.3.5)
set(GLOG_ROOT_DIR "C:/car_libs/glog")

find_path(GLOG_INCLUDE_DIR NAMES glog/logging.h PATHS "${GLOG_ROOT_DIR}/include")
mark_as_advanced(GLOG_INCLUDE_DIR) # show entry in cmake-gui

find_library(GLOG_LIBRARY NAMES glog.lib PATHS "${GLOG_ROOT_DIR}/lib")
mark_as_advanced(GLOG_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR} )
set(GLOG_LIBRARIES ${GLOG_LIBRARY} )

message( "glog-config.cmake " ${GLOG_ROOT_DIR})

mysqlconcpp-config.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
set(MYSQLCPPCONN_FOUND TRUE) # auto 
set(MYSQLCPPCONN_VERSION 1.1)
set(MYSQLCPPCONN_ROOT_DIR "C:/car_libs/mysqlcppconn")

find_path(MYSQLCPPCONN_INCLUDE_DIR NAMES cppconn/driver.h PATHS "${MYSQLCPPCONN_ROOT_DIR}/include")
mark_as_advanced(MYSQLCPPCONN_INCLUDE_DIR) # show entry in cmake-gui

find_library(MYSQLCPPCONN_LIBRARY NAMES mysqlcppconn.lib PATHS "${MYSQLCPPCONN_ROOT_DIR}/lib/opt")
mark_as_advanced(MYSQLCPPCONN_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(MYSQLCPPCONN_INCLUDE_DIRS ${MYSQLCPPCONN_INCLUDE_DIR} )
set(MYSQLCPPCONN_LIBRARIES ${MYSQLCPPCONN_LIBRARY} )

# cmake entry will be saved to build/CMakeCache.txt

message( "mysqlcppconn-config.cmake " ${MYSQLCPPCONN_ROOT_DIR})

libjpegturbo-config.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
set(LIBJPEGTURBO_FOUND TRUE) # auto 
set(LIBJPEGTURBO_VERSION 1.5.4)
set(LIBJPEGTURBO_ROOT_DIR "C:/car_libs/libjpeg-turbo64")

find_path(LIBJPEGTURBO_INCLUDE_DIR NAMES jpeglib.h turbojpeg.h PATHS "${LIBJPEGTURBO_ROOT_DIR}/include")
mark_as_advanced(LIBJPEGTURBO_INCLUDE_DIR) # show entry in cmake-gui

find_library(LIBJPEGTURBO_JPEG_LIBRARY NAMES jpeg.lib PATHS "${LIBJPEGTURBO_ROOT_DIR}/lib")
mark_as_advanced(LIBJPEGTURBO_JPEG_LIBRARY) # show entry in cmake-gui

find_library(LIBJPEGTURBO_TURBOJPEG_LIBRARY NAMES turbojpeg.lib PATHS "${LIBJPEGTURBO_ROOT_DIR}/lib")
mark_as_advanced(LIBJPEGTURBO_TURBOJPEG_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(LIBJPEGTURBO_INCLUDE_DIRS ${LIBJPEGTURBO_INCLUDE_DIR} )
set(LIBJPEGTURBO_LIBRARIES ${LIBJPEGTURBO_JPEG_LIBRARY} ${LIBJPEGTURBO_TURBOJPEG_LIBRARY} )

message( "libjpegturbo-config.cmake " ${LIBJPEGTURBO_ROOT_DIR})

winpcap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
set(WINPCAP_FOUND TRUE) # auto 
set(WINPCAP_VERSION 1.0.0)
set(WINPCAP_ROOT_DIR "C:/car_libs/winpcap")

find_path(WINPCAP_INCLUDE_DIR NAMES pcap.h PATHS "${WINPCAP_ROOT_DIR}/Include")
mark_as_advanced(WINPCAP_INCLUDE_DIR) # show entry in cmake-gui

find_library(WINPCAP_LIBRARY NAMES wpcap.lib PATHS "${WINPCAP_ROOT_DIR}/Lib")
mark_as_advanced(WINPCAP_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(WINPCAP_INCLUDE_DIRS ${WINPCAP_INCLUDE_DIR} )
set(WINPCAP_LIBRARIES ${WINPCAP_LIBRARY} )

message( "winpcap-config.cmake " ${WINPCAP_ROOT_DIR})

OpenNI2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
set(OPENNI2_FOUND TRUE) # auto 
set(OPENNI2_VERSION 1.0.0)
set(OPENNI2_ROOT_DIR "C:/car_libs/OpenNI2")

find_path(OPENNI2_INCLUDE_DIR NAMES OpenNI.h PATHS "${OPENNI2_ROOT_DIR}/Include")
mark_as_advanced(OPENNI2_INCLUDE_DIR) # show entry in cmake-gui

find_library(OPENNI2_LIBRARY NAMES OpenNI2.lib PATHS "${OPENNI2_ROOT_DIR}/Lib")
mark_as_advanced(OPENNI2_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(OPENNI2_INCLUDE_DIRS ${OPENNI2_INCLUDE_DIR} )
set(OPENNI2_LIBRARIES ${OPENNI2_LIBRARY} )

message( "openni2-config.cmake " ${OPENNI2_ROOT_DIR})

CMake Options

how to find_package

CMAKE_PREFIX_PATH + find_package

1
2
3
4
5
6
7
8
9
10
set(ROOT_CMAKE_DIR /home/user/program/anakin/sdk/cmake)
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${ROOT_CMAKE_DIR};${CMAKE_PREFIX_PATH}")
MESSAGE( [cmake] " CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH} for find_package")

# find anakin-config.cmake file in CMAKE_PREFIX_PATH
find_package(ANAKIN REQUIRED)
include_directories(${ANAKIN_INCLUDE_DIRS})

message( [anakin] ${ANAKIN_INCLUDE_DIRS} )
message( [anakin] ${ANAKIN_LIBRARIES} )

include xxx-config.cmake

1
2
3
4
5
include(cmake/anakin-config.cmake)
include_directories(${ANAKIN_INCLUDE_DIRS})

message( [anakin] ${ANAKIN_INCLUDE_DIRS} )
message( [anakin] ${ANAKIN_LIBRARIES} )

c++11

1
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

Reference

History

  • 20180208: created.
  • 20180301: add xxx-config.cmake.

Series

Guide

version

gflags

do not use offical version,instead use https://github.com/schuhschuh/gflags.git

1
2
3
4
5
git clone https://github.com/schuhschuh/gflags.git 
cd gflags
mkdir windows-build
cd windows-build
cmake-gui ..

with options

BUILD_SHARED_LIBS ON 
INSTALL_SHARED_LIBS ON
INSTALL_STATIC_LIBS OFF
CMAKE_CONFIGURATION_TYPES Release # Release
REGISTER_INSTALL_PREFIX OFF

CMAKE_INSTALL_PREFIX D:/gflags
#NAMESPACE google;gflags
NAMESPACE google

or command

1
cmake -DGFLAGS_NAMESPACE=google -DCMAKE_CXX_FLAGS=-fPIC ..

we get include and lib/gflags.lib, and bin/gflags.dll
modify CMAKE/CMAKE_INSTALL_PREFIX to a non-system folder, otherwise you will need administrative privileges to run INSTALL project.

glog

Notice:
we have to new entry with BUILD_SHARED_LIB with value ON , because by default, glog is static library with extension .lib.

1
2
3
4
5
wget https://github.com/google/glog/archive/v0.3.5.zip

mkdir windows-build
cd windows-build
cmake-gui ..

with options

#WITH_GFLAGS ON 
#gflags_DIR D:/gflags/lib/cmake/gflags

WITH_GFLAGS OFF
CMAKE_INSTALL_DIR d:/glog
CMAKE_CONFIGURATION_TYPES Release # Release

BUILD_SHARED_LIBS ON  # new by hand

generate sln and open with Visual Studio 2015 compile and install.

and we get preprocessors from glog

WIN32
_WINDOWS
NDEBUG
GLOG_NO_ABBREVIATED_SEVERITIES
GOOGLE_GLOG_IS_A_DLL=1
GOOGLE_GLOG_DLL_DECL=__declspec(dllexport)
GFLAGS_IS_A_DLL=1
CMAKE_INTDIR="Release"
LIBGLOG_EXPORTS

we get include and lib/glog.lib, and bin/glog.dll

multiple processor compile

  • windows: set_target_properties(main PROPERTIES COMPILE_FLAGS "/MP")
  • linux: make -j8

with cmake options /MD added to CMAKE_CXX_FLAGS_RELEASE

CMAKE_CXX_FLAGS_RELEASE /MD /O2 /Ob2 /DNDEBUG /MP

or

with CMakeLists.txt

1
2
3
4
5
if(MSVC) # WIN32
set_target_properties(target1 PROPERTIES COMPILE_FLAGS "/MP")
set_target_properties(target2 PROPERTIES COMPILE_FLAGS "/MP")
set_target_properties(target3 PROPERTIES COMPILE_FLAGS "/MP")
endif()

project dependency

select ALL-BUILD and change build order by hand.

ZERO_CHECK
CarConfig
CarUtil
CarModel
CarDatabase
a_main
a_unit_tests
data_client
data_server
example_jpeg
example_thread
ALL_BUILD

Example Code

CMakeLists.txt

1
2
3
4
5
6
7
#find_package(glog 0.3.5 REQUIRED)  
# no GLOG_INCLUDE_DIRS GLOG_LIBRARIES, we only use `glog::glog` as target

find_package(glog REQUIRED)

add_executable(main main.cpp)
target_link_libraries (main glog::glog)

glog include directory will be imported automatically.

gflags-config.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
set(GFLAGS_FOUND TRUE) # auto 
set(GFLAGS_ROOT_DIR "D:/gflags")

find_path(GFLAGS_INCLUDE_DIR NAMES gflags/gflags.h PATHS "${GFLAGS_ROOT_DIR}/include")
mark_as_advanced(GFLAGS_INCLUDE_DIR) # show entry in cmake-gui

find_library(GFLAGS_LIBRARY NAMES gflags.lib PATHS "${GFLAGS_ROOT_DIR}/lib")
mark_as_advanced(GFLAGS_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(GFLAGS_INCLUDE_DIRS ${GFLAGS_INCLUDE_DIR} )
set(GFLAGS_LIBRARIES ${GFLAGS_LIBRARY} )

message( "gflags-config.cmake " ${GFLAGS_ROOT_DIR})

glog-config.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
set(GLOG_FOUND TRUE) # auto 
set(GLOG_ROOT_DIR "D:/glog")

find_path(GLOG_INCLUDE_DIR NAMES glog/logging.h PATHS "${GLOG_ROOT_DIR}/include")
mark_as_advanced(GLOG_INCLUDE_DIR) # show entry in cmake-gui

find_library(GLOG_LIBRARY NAMES glog.lib PATHS "${GLOG_ROOT_DIR}/lib")
mark_as_advanced(GLOG_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR} )
set(GLOG_LIBRARIES ${GLOG_LIBRARY} )

message( "glog-config.cmake " ${GLOG_ROOT_DIR})

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <gflags/gflags.h>
#include <glog/logging.h>

int main(int argc, char **argv)
{
/*
FLAGS_logtostderr = true;
FLAGS_alsologtostderr = true;
FLAGS_colorlogtostderr = true;
FLAGS_log_prefix = true;

FLAGS_logbufsecs = 0; //0 means realtime
FLAGS_max_log_size = 10; // MB
*/
google::InitGoogleLogging(argv[0]); // init google logging
google::SetLogDestination(google::GLOG_FATAL, "../log/log_fatal_");
google::SetLogDestination(google::GLOG_ERROR, "../log/log_error_");
google::SetLogDestination(google::GLOG_WARNING, "../log/log_warning_");
google::SetLogDestination(google::GLOG_INFO, "../log/log_info_");

LOG(INFO) << "Hello GLOG";

return 0;
}

copy gflags.dll and glog.dll to main executable folder.

errors

error:

fatal error C1189: #error :  ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.  

solution:

1
2
3
4
5
6
7
find_package(GFLAGS REQUIRED) # user-defined
find_package(GLOG REQUIRED) # user-defined
include_directories(${GFLAGS_INCLUDE_DIRS})
include_directories(${GLOG_INCLUDE_DIRS})

# add macro GLOG_NO_ABBREVIATED_SEVERITIES
add_definitions( -DGLOG_NO_ABBREVIATED_SEVERITIES )

Reference

History

  • 20180206: created.
  • 20180207: add multiple processor and build dependency part for windows.
  • 20180209: add error and solutions

Guide

copy constructors and copy assignment operators

1
2
MemoryBlock(const MemoryBlock& other)
MemoryBlock& operator=(const MemoryBlock& other)

move constructors and move assignment operators

1
2
MemoryBlock(MemoryBlock&& other)  
MemoryBlock& operator=(MemoryBlock&& other)

example_move

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#include <iostream>
#include <stdio.h>

#include <utility>
#include <vector>
#include <string>

class MemoryBlock
{
public:

// Simple constructor that initializes the resource.
explicit MemoryBlock(size_t length)
: _length(length)
, _data(new int[length])
{
std::cout << "In MemoryBlock(size_t). length = "
<< _length << "." << std::endl;
}

// Destructor.
~MemoryBlock()
{
std::cout << "In ~MemoryBlock(). length = "
<< _length << ".";

if (_data != nullptr)
{
std::cout << " Deleting resource.";
// Delete the resource.
delete[] _data;
}

std::cout << std::endl;
}

// Copy constructor.
MemoryBlock(const MemoryBlock& other)
: _length(other._length)
, _data(new int[other._length])
{
std::cout << "In MemoryBlock(const MemoryBlock&). length = "
<< other._length << ". Copying resource." << std::endl;

std::copy(other._data, other._data + _length, _data);
}

// Copy assignment operator.
MemoryBlock& operator=(const MemoryBlock& other)
{
std::cout << "In operator=(const MemoryBlock&). length = "
<< other._length << ". Copying resource." << std::endl;

if (this != &other)
{
// Free the existing resource.
delete[] _data;

_length = other._length;
_data = new int[_length];
std::copy(other._data, other._data + _length, _data);
}
return *this;
}

// Retrieves the length of the data resource.
size_t Length() const
{
return _length;
}

// Move constructor.
MemoryBlock(MemoryBlock&& other)
: _data(nullptr)
, _length(0)
{
std::cout << "In MemoryBlock(MemoryBlock&&). length = "
<< other._length << ". Moving resource." << std::endl;

// Copy the data pointer and its length from the
// source object.
_data = other._data;
_length = other._length;

// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
other._data = nullptr;
other._length = 0;
}

// Move assignment operator.
MemoryBlock& operator=(MemoryBlock&& other)
{
std::cout << "In operator=(MemoryBlock&&). length = "
<< other._length << "." << std::endl;

if (this != &other)
{
// Free the existing resource.
delete[] _data;

// Copy the data pointer and its length from the
// source object.
_data = other._data;
_length = other._length;

// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
other._data = nullptr;
other._length = 0;
}
return *this;
}

private:
size_t _length; // The length of the resource.
int* _data; // The resource.
};

void TestSTLObject()
{
std::string str = "Hello";
std::vector<std::string> v;

// uses the push_back(const T&) overload, which means
// we'll incur the cost of copying str
v.push_back(str);
std::cout << "After copy, str is \"" << str << "\"\n";

// uses the rvalue reference push_back(T&&) overload,
// which means no strings will be copied; instead, the contents
// of str will be moved into the vector. This is less
// expensive, but also means str might now be empty.
v.push_back(std::move(str));
std::cout << "After move, str is \"" << str << "\"\n";

std::cout << "The contents of the vector are \"" << v[0]
<< "\", \"" << v[1] << "\"\n";

/*
After copy, str is "Hello"
After move, str is ""
The contents of the vector are "Hello", "Hello"
*/
}

void TestMyObjectWithoutUseMove()
{
std::vector<MemoryBlock> v;
MemoryBlock mb1(25);
//MemoryBlock mb2(75);
//MemoryBlock mb3(50);

v.push_back(mb1);
//v.push_back(mb2);
//v.push_back(mb3);

/*
In MemoryBlock(size_t). length = 25.
In MemoryBlock(const MemoryBlock&). length = 25. Copying resource.
In ~MemoryBlock(). length = 25. Deleting resource.
In ~MemoryBlock(). length = 25. Deleting resource.
*/
}

void TestMyObjectWithUseMove()
{
std::vector<MemoryBlock> v;

MemoryBlock mb1(25);
// MemoryBlock mb2(75);
// MemoryBlock mb3(50);

v.push_back(std::move(mb1));
//v.push_back(MemoryBlock(75));
//v.insert(v.begin() + 1, MemoryBlock(50));

/*
In MemoryBlock(size_t). length = 25.
In MemoryBlock(MemoryBlock&&). length = 25. Moving resource.
In ~MemoryBlock(). length = 0.
In ~MemoryBlock(). length = 25. Deleting resource.
*/
}

int main(int argc, char const *argv[])
{
//TestSTLObject();
//TestMyObjectWithoutUseMove();
TestMyObjectWithUseMove();
return 0;
}

rewrite move constructor

1
2
3
4
5
6
7
// Move constructor.  
MemoryBlock(MemoryBlock&& other)
: _data(nullptr)
, _length(0)
{
*this = std::move(other);
}

Reference

History

  • 20180201: created.

Series

Guide

build requirements

Build Requirements

  • cmake 2.8
  • NASM 2.13
  • Visual Studio 2015
  • libjpeg-turbo 1.5.4

If using NASM, 2.05 or later is required for an x86-64 build.
nasm.exe/yasm.exe should be in your PATH.

download

1
2
3
git clone https://github.com/libjpeg-turbo/libjpeg-turbo.git
# or
wget https://codeload.github.com/libjpeg-turbo/libjpeg-turbo/zip/master

install nasm

1
wget http://www.nasm.us/pub/nasm/releasebuilds/2.13.03rc1/win64/nasm-2.13.03rc1-installer-x64.exe

add C:\Program Files\NASM to env path.

compile libjpeg

1
cmake-gui ..

with options

CMAKE_BUILD_TYPE = Release
ENABLE_SHARED = ON
CMAKE_INSTALL_PREFIX = d:/libjpeg-turbo64
NASM = C:/Program Files/NASM/nasm.exe

configure and generate sln, compile with visual studio 2015 and install.

usage with cmake

libjpegturbo-config.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
set(LIBJPEGTURBO_FOUND TRUE) # auto 
set(LIBJPEGTURBO_ROOT_DIR "d:/libjpeg-turbo64")

find_path(LIBJPEGTURBO_INCLUDE_DIR NAMES jpeglib.h turbojpeg.h PATHS "${LIBJPEGTURBO_ROOT_DIR}/include")
mark_as_advanced(LIBJPEGTURBO_INCLUDE_DIR) # show entry in cmake-gui

find_library(LIBJPEGTURBO_JPEG_LIBRARY NAMES jpeg.lib PATHS "${LIBJPEGTURBO_ROOT_DIR}/lib")
mark_as_advanced(LIBJPEGTURBO_JPEG_LIBRARY) # show entry in cmake-gui

find_library(LIBJPEGTURBO_TURBOJPEG_LIBRARY NAMES turbojpeg.lib PATHS "${LIBJPEGTURBO_ROOT_DIR}/lib")
mark_as_advanced(LIBJPEGTURBO_TURBOJPEG_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(LIBJPEGTURBO_INCLUDE_DIRS ${LIBJPEGTURBO_INCLUDE_DIR} )
set(LIBJPEGTURBO_LIBRARIES ${LIBJPEGTURBO_JPEG_LIBRARY} ${LIBJPEGTURBO_TURBOJPEG_LIBRARY} )

message( "libjpegturbo-config.cmake " ${LIBJPEGTURBO_ROOT_DIR})

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 find_package(LIBJPEGTURBO REQUIRED)
include_directories(${LIBJPEGTURBO_INCLUDE_DIRS})

add_executable (example_jpeg
${CMAKE_CURRENT_SOURCE_DIR}/src/example/example_jpeg.cpp
)

target_link_libraries (example_jpeg
${LIBJPEGTURBO_LIBRARIES}
)

add_executable (example_turbojpeg
${CMAKE_CURRENT_SOURCE_DIR}/src/example/example_turbojpeg.cpp
)

target_link_libraries (example_turbojpeg
${LIBJPEGTURBO_LIBRARIES}
)

Example Code

jpeglib vs turbojpeg

jpeglib

  • include: #include "jpeglib.h"
  • lib: jpeg.lib
  • dll: jpeg62.dll

turbojpeg

  • include: #include "turbojpeg.h"
  • lib: turbojpeg.lib
  • dll: turbojpeg.dll

turbojpeg is (3-5x) faster than jpeglib.

jpeglib

see jpeglib.cpp

turbojpeg

see turbojpeg.cpp

Reference

History

  • 20180201: created.
  • 20180202: add example code.

Series

Guide

apt-get

1
2
# 1.58 for ubuntu 16.04
sudo apt-get install libboost-all-dev

compile from source

1
2
3
4
5
6
7
8
9
10
11
12
13
14
wget https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.gz

tar xzvf boost_1_66_0.tar.gz
cd boost_1_66_0/

sudo apt-get update
sudo apt-get install build-essential g++ python-dev autotools-dev libicu-dev build-essential libbz2-dev

./bootstrap.sh --prefix=/usr/local/

./b2 --help

./b2 -j8 variant=release link=shared threading=multi runtime-link=shared
sudo ./b2 -j8 install

thread example

thread_demo.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//#include <boost/thread/thread.hpp>
//#include <boost/thread/mutex.hpp>
//#include <boost/bind/bind.hpp>
#include <iostream>

#include <boost/thread.hpp>
#include <boost/bind.hpp>

boost::mutex io_mutex;

void count(int id)
{
for (int i = 0; i < 10; i++)
{
boost::mutex::scoped_lock lock(io_mutex);
std::cout << id << ":" << i << std::endl;
}
}

int main(int argc, char* argv[])
{
boost::thread thrd1(boost::bind(&count, 1));
boost::thread thrd2(boost::bind(&count, 2));
thrd1.join();
thrd2.join();
return 0;
}

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
cmake_minimum_required (VERSION 2.6)

project (thread_main)
enable_language(C)
enable_language(CXX)

set(Boost_USE_RELEASE_LIBS ON)
#set(Boost_USE_STATIC_LIBS OFF) # use .a or .so file
set(Boost_USE_MULTITHREAD ON)

# Find Boost package 1.5.8 or 1.6.6
find_package(Boost 1.5.8 REQUIRED COMPONENTS serialization date_time system filesystem thread timer)
include_directories(${Boost_INCLUDE_DIRS})

add_executable (thread_main
thread_main.cpp
)

target_link_libraries (thread_main
${Boost_LIBRARIES}
)

thread pool

see thread pool with boost

Reference

History

  • 20180131: created.

Guide

how to serialize string

size + data

The easiest serialization method for strings or other blobs with variable size is to serialize first the size as you serialize integers, then just copy the content to the output stream.

When reading you first read the size, then allocate the string and then fill it by reading the correct number of bytes from the stream.

with ostream/istream

native way with ostream/istream for example class MyClass with height,width,name fields.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class MyClass {
public:
int height;
int width;
std::string name;
}

std::ostream& MyClass::serialize(std::ostream &out) const {
out << height;
out << ',' //number seperator
out << width;
out << ',' //number seperator
out << name.size(); //serialize size of string
out << ',' //number seperator
out << name; //serialize characters of string
return out;
}
std::istream& MyClass::deserialize(std::istream &in) {
if (in) {
int len=0;
char comma;
in >> height;
in >> comma; //read in the seperator
in >> width;
in >> comma; //read in the seperator
in >> len; //deserialize size of string
in >> comma; //read in the seperator
if (in && len) {
std::vector<char> tmp(len);
in.read(tmp.data() , len); //deserialize characters of string
name.assign(tmp.data(), len);
}
}
return in;
}

overload for operator<< and operator>>

1
2
3
4
5
6
7
8
9
10
11
std::ostream& operator<<(std::ostream& out, const MyClass &obj)
{
obj.serialize(out);
return out;
}

std::istream& operator>>(std::istream& in, MyClass &obj)
{
obj.deserialize(in);
return in;
}

with boost serialization

archive file format

  • text: text_iarchive,text_oarchive field
  • xml: xml_iarchive,xml_oarchive, with BOOST_SERIALIZATION_NVP(field)
  • binary: binary_iarchive,binary_oarchive with stringstream or fstream.

text archive

change BOOST_SERIALIZATION_NVP(field) to field

xml archive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <boost/archive/text_iarchive.hpp> 
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <iostream>
#include <fstream>
#include <sstream>

class Camera {

public:
int id;
std::string name;
double pos;
};

namespace boost {
namespace serialization {

template<class Archive>
void serialize(Archive& archive, Camera& cam, const unsigned int version)
{
archive & BOOST_SERIALIZATION_NVP(cam.id);
archive & BOOST_SERIALIZATION_NVP(cam.name);
archive & BOOST_SERIALIZATION_NVP(cam.pos);
}

} // namespace serialization
} // namespace boost

std::ostream& operator<<(std::ostream& cout, const Camera& cam)
{
cout << cam.id << std::endl
<< cam.name << std::endl
<< cam.pos << std::endl;
return cout;
}

void save()
{
std::ofstream file("archive.xml");
boost::archive::xml_oarchive oa(file);

Camera cam;
cam.id = 100;
cam.name = "new camera";
cam.pos = 99.88;

oa & BOOST_SERIALIZATION_NVP(cam);
}

void load()
{
std::ifstream file("archive.xml");
boost::archive::xml_iarchive ia(file);
Camera cam;
ia & BOOST_SERIALIZATION_NVP(cam);
std::cout << cam << std::endl;
}

void test_camera()
{
save();
load();
}

int main(int argc, char** argv)
{
test_camera();
}

binary archive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void save_load_with_binary_archive()
{
// binary archive with stringstream
std::ostringstream oss;
boost::archive::binary_oarchive oa(oss);

Camera cam;
cam.id = 100;
cam.name = "new camera";
cam.pos = 99.88;

oa & (cam);

// get binary content
std::string str_data = oss.str();
std::istringstream iss(str_data);
boost::archive::binary_iarchive ia(iss);
Camera new_cam;
ia & (new_cam);
std::cout << new_cam << std::endl;
}

binary archive with poco SocketStream

client.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void test_client()
{
SocketAddress address("127.0.0.1", 9911);
StreamSocket socket(address);
SocketStream stream(socket);
//Poco::StreamCopier::copyStream(stream, std::cout);

boost::archive::binary_oarchive oa(stream);
Camera cam;
cam.id = 100;
cam.name = "new camera";
cam.pos = 99.88;

oa & (cam);
}

server.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void run()
{
Application& app = Application::instance();
app.logger().information("Request from " + this->socket().peerAddress().toString());
try
{
SocketStream stream(this->socket());
//Poco::StreamCopier::copyStream(stream, std::cout);

boost::archive::binary_iarchive ia(stream);
Camera new_cam;
ia & (new_cam);
std::cout << new_cam << std::endl;
}
catch (Poco::Exception& exc)
{
app.logger().log(exc);
}
}

notes on std::string

Even know you have seen that they do the same, or that .data() calls .c_str(), it is not correct to assume that this will be the case for other compilers. It is also possible that your compiler will change with a future release.

2 reasons to use std::string:

std::string can be used for both text and arbitrary binary data.

1
2
3
4
5
6
7
8
9
10
11
//Example 1
//Plain text:
std::string s1;
s1 = "abc";
s1.c_str();

//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("a\0b\0b\0", 6);
s2.data();

boost archive style

intrusive

  • private template<class Archive> void serialize(Archive& archive, const unsigned int version)
  • friend class boost::serialization::access;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Camera {

public:
int id;
std::string name;
double pos;

private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive& archive, const unsigned int version)
{
archive & BOOST_SERIALIZATION_NVP(id);
archive & BOOST_SERIALIZATION_NVP(name);
archive & BOOST_SERIALIZATION_NVP(pos);
}
};

non-intrusive

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Camera {

public:
int id;
std::string name;
double pos;
};


namespace boost {
namespace serialization {

template<class Archive>
void serialize(Archive& archive, Camera& cam, const unsigned int version)
{
archive & BOOST_SERIALIZATION_NVP(cam.id);
archive & BOOST_SERIALIZATION_NVP(cam.name);
archive & BOOST_SERIALIZATION_NVP(cam.pos);
}

} // namespace serialization
} // namespace boost

boost archive type

shared_ptr

boost::shared_ptr<T> instead of std::shared_prt<T>
and

#include <boost/serialization/shared_ptr.hpp>

Reference

History

  • 20180128: created.
  • 20180129: add intrusive,non-intrusive part.

Series

Guide

download

1
2
wget https://pocoproject.org/releases/poco-1.8.1/poco-1.8.1.zip
wget https://pocoproject.org/releases/poco-1.8.1/poco-1.8.1.tar.gz

build

build options

buildwin.cmd

1
2
3
4
5
6
7
8
9
10
11
rem Usage:
rem ------
rem buildwin VS_VERSION [ACTION] [LINKMODE] [CONFIGURATION] [PLATFORM] [SAMPLES] [TESTS] [TOOL]
rem VS_VERSION: 90|100|110|120|140|150
rem ACTION: build|rebuild|clean
rem LINKMODE: static_mt|static_md|shared|all
rem CONFIGURATION: release|debug|both
rem PLATFORM: Win32|x64|WinCE|WEC2013
rem SAMPLES: samples|nosamples
rem TESTS: tests|notests
rem TOOL: devenv|vcexpress|wdexpress|msbuild

we choose to build with visual studio 2015

build_vs140.cmd

1
2
@echo off
buildwin 140 build shared release x64 samples

build

1
./build_vs140.cmd

or

1
cmake-gui ..

cmake-gui and open sln to build with release x64and install to C:/Program Files/Poco so that find_package(Poco REQURIED) take effect.

1
2
3
4
5
6
7
8
9
10
11
12
13
$ ls Poco

bin include lib

$ ll Poco/lib

total 3.5M
drwxr-xr-x 1 zunli zunli 0 Jan 25 07:39 cmake
-rw-r--r-- 1 zunli zunli 1.5M Jan 25 06:59 PocoFoundation.lib
-rw-r--r-- 1 zunli zunli 111K Jan 25 06:59 PocoJSON.lib
-rw-r--r-- 1 zunli zunli 1007K Jan 25 07:00 PocoNet.lib
-rw-r--r-- 1 zunli zunli 320K Jan 25 07:00 PocoUtil.lib
-rw-r--r-- 1 zunli zunli 595K Jan 25 07:00 PocoXML.lib

Poco Example

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
cmake_minimum_required (VERSION 2.6)

project (event_demo)
enable_language(C)
enable_language(CXX)

# Always include the source and build directories in the include path.
set(CMAKE_INCLUDE_CURRENT_DIR ON)

# Set the output folder where your program will be created
set(CMAKE_BINARY_DIR ${CMAKE_SOURCE_DIR}/bin)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR})

find_package(Poco REQUIRED COMPONENTS Foundation Util Net XML JSON)

# no Poco_INCLUDE_DIRS, we have to set by hand
if(MSVC) # WIN32
SET(Poco_INCLUDE_DIRS "C:/Program Files/Poco/include")
else()
SET(Poco_INCLUDE_DIRS "/usr/local/include/Poco")
endif(MSVC)

MESSAGE( [Main] " Poco_INCLUDE_DIRS = ${Poco_INCLUDE_DIRS}")
MESSAGE( [Main] " Poco_LIBRARIES = ${Poco_LIBRARIES}")

# The following folder will be included
include_directories(
${MY_SRC_INCLUDE}
${Poco_INCLUDE_DIRS}
)

link_directories(${CMAKE_BINARY_DIR})

add_executable(event_demo event_demo.cpp)
target_link_libraries(event_demo ${Poco_LIBRARIES})

Notice 1: find_package(Poco REQUIRED COMPONENTS Foundation Util Net XML JSON) and use ${Poco_INCLUDE_DIRS}, ${Poco_LIBRARIES}.

Notice 2: we have to set SET(Poco_INCLUDE_DIRS "C:/Program Files/Poco/include") by hand.

event

event_demo.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include "Poco/BasicEvent.h"
#include "Poco/Delegate.h"
#include <iostream>

using Poco::BasicEvent;
using Poco::Delegate;

class Source
{
public:
BasicEvent<int> theEvent;

void fireEvent(int n)
{
theEvent(this, n);
}
};

class Target
{
public:
void onEvent(const void* pSender, int& arg)
{
std::cout << "onEvent: " << arg << std::endl;
}
};

int main(int argc, char** argv)
{
Source source;
Target target;

source.theEvent += Delegate<Target, int>(
&target, &Target::onEvent);

source.fireEvent(42);

source.theEvent -= Delegate<Target, int>(
&target, &Target::onEvent);

return 0;
}

active method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "Poco/ActiveMethod.h"
#include "Poco/ActiveResult.h"
#include <utility>
#include <iostream>

using Poco::ActiveMethod;
using Poco::ActiveResult;

class ActiveAdder
{
public:
ActiveAdder() : add(this, &ActiveAdder::addImpl)
{
}

ActiveMethod<int, std::pair<int, int>, ActiveAdder> add;

private:
int addImpl(const std::pair<int, int>& args)
{
return args.first + args.second;
}
};

int main(int argc, char** argv)
{
ActiveAdder adder;

ActiveResult<int> sum = adder.add(std::make_pair(1, 2));
// do other things
sum.wait();
std::cout << sum.data() << std::endl;

return 0;
}

http server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#include "Poco/Net/HTTPServer.h"
#include "Poco/Net/HTTPRequestHandler.h"
#include "Poco/Net/HTTPRequestHandlerFactory.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/HTTPServerRequest.h"
#include "Poco/Net/HTTPServerResponse.h"
#include "Poco/Net/HTTPServerParams.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Timestamp.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Exception.h"
#include "Poco/ThreadPool.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>

using Poco::Net::ServerSocket;
using Poco::Net::HTTPRequestHandler;
using Poco::Net::HTTPRequestHandlerFactory;
using Poco::Net::HTTPServer;
using Poco::Net::HTTPServerRequest;
using Poco::Net::HTTPServerResponse;
using Poco::Net::HTTPServerParams;
using Poco::Timestamp;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::ThreadPool;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::OptionCallback;
using Poco::Util::HelpFormatter;

class TimeRequestHandler : public HTTPRequestHandler
{
public:
TimeRequestHandler(const std::string& format) : _format(format)
{
}

void handleRequest(HTTPServerRequest& request,
HTTPServerResponse& response)
{
Application& app = Application::instance();
app.logger().information("[LOG] Request from "
+ request.clientAddress().toString());

Timestamp now;
std::string dt(DateTimeFormatter::format(now, _format));

response.setChunkedTransferEncoding(true);
response.setContentType("text/html");

std::ostream& ostr = response.send();
ostr << "<html><head><title>HTTPTimeServer powered by "
"POCO C++ Libraries</title>";
ostr << "<meta http-equiv=\"refresh\" content=\"1\"></head>";
ostr << "<body><p style=\"text-align: center; "
"font-size: 48px;\">";
ostr << dt;
ostr << "</p></body></html>";
}

private:
std::string _format;
};

class TimeRequestHandlerFactory : public HTTPRequestHandlerFactory
{
public:
TimeRequestHandlerFactory(const std::string& format) :
_format(format)
{
}

HTTPRequestHandler* createRequestHandler(
const HTTPServerRequest& request)
{
if (request.getURI() == "/")
return new TimeRequestHandler(_format);
else
return 0;
}

private:
std::string _format;
};

class HTTPTimeServer : public Poco::Util::ServerApplication
{
public:
HTTPTimeServer() : _helpRequested(false)
{
}

~HTTPTimeServer()
{
}

protected:
void initialize(Application& self)
{
Application& app = Application::instance();
app.logger().information("[HTTPTimeServer] initialize port=9980 ");

loadConfiguration();
ServerApplication::initialize(self);
}

void uninitialize()
{
Application& app = Application::instance();
app.logger().information("[HTTPTimeServer] uninitialize ");

ServerApplication::uninitialize();
}

void defineOptions(OptionSet& options)
{
ServerApplication::defineOptions(options);

options.addOption(
Option("help", "h", "display argument help information")
.required(false)
.repeatable(false)
.callback(OptionCallback<HTTPTimeServer>(
this, &HTTPTimeServer::handleHelp)));
}

void handleHelp(const std::string& name,
const std::string& value)
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader(
"A web server that serves the current date and time.");
helpFormatter.format(std::cout);
stopOptionsProcessing();
_helpRequested = true;
}

int main(const std::vector<std::string>& args)
{
Application& app = Application::instance();
app.logger().information("[HTTPTimeServer] main ");

if (!_helpRequested)
{
unsigned short port = (unsigned short)
config().getInt("HTTPTimeServer.port", 9980);
std::string format(
config().getString("HTTPTimeServer.format",
DateTimeFormat::SORTABLE_FORMAT));

ServerSocket svs(port);
HTTPServer srv(new TimeRequestHandlerFactory(format),
svs, new HTTPServerParams);
srv.start();
waitForTerminationRequest();
srv.stop();
}
return Application::EXIT_OK;
}

private:
bool _helpRequested;
};

int main(int argc, char** argv)
{
HTTPTimeServer app;
return app.run(argc, argv);
//visit http://localhost:9980
}

tcp server/client

tcpserver

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
//
// TimeServer.cpp
//
// This sample demonstrates the TCPServer and ServerSocket classes.
//
// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//


#include "Poco/Net/TCPServer.h"
#include "Poco/Net/TCPServerConnection.h"
#include "Poco/Net/TCPServerConnectionFactory.h"
#include "Poco/Net/TCPServerParams.h"
#include "Poco/Net/StreamSocket.h"
#include "Poco/Net/ServerSocket.h"
#include "Poco/Timestamp.h"
#include "Poco/DateTimeFormatter.h"
#include "Poco/DateTimeFormat.h"
#include "Poco/Exception.h"
#include "Poco/Util/ServerApplication.h"
#include "Poco/Util/Option.h"
#include "Poco/Util/OptionSet.h"
#include "Poco/Util/HelpFormatter.h"
#include <iostream>


using Poco::Net::ServerSocket;
using Poco::Net::StreamSocket;
using Poco::Net::TCPServerConnection;
using Poco::Net::TCPServerConnectionFactory;
using Poco::Net::TCPServer;
using Poco::Timestamp;
using Poco::DateTimeFormatter;
using Poco::DateTimeFormat;
using Poco::Util::ServerApplication;
using Poco::Util::Application;
using Poco::Util::Option;
using Poco::Util::OptionSet;
using Poco::Util::HelpFormatter;


class TimeServerConnection : public TCPServerConnection
/// This class handles all client connections.
///
/// A string with the current date and time is sent back to the client.
{
public:
TimeServerConnection(const StreamSocket& s, const std::string& format) :
TCPServerConnection(s),
_format(format)
{
}

void run()
{
Application& app = Application::instance();
app.logger().information("Request from " + this->socket().peerAddress().toString());
try
{
Timestamp now;
//std::string dt(DateTimeFormatter::format(now, _format));
//dt.append("\r\n");
std::string dt("hello world");
std::string info("sending: [" + dt + "] with length="+std::to_string(dt.length()) );
app.logger().information(info);
socket().sendBytes(dt.data(), (int)dt.length());
}
catch (Poco::Exception& exc)
{
app.logger().log(exc);
}
}

private:
std::string _format;
};


class TimeServerConnectionFactory : public TCPServerConnectionFactory
/// A factory for TimeServerConnection.
{
public:
TimeServerConnectionFactory(const std::string& format) :
_format(format)
{
}

TCPServerConnection* createConnection(const StreamSocket& socket)
{
return new TimeServerConnection(socket, _format);
}

private:
std::string _format;
};


class TimeServer : public Poco::Util::ServerApplication
/// The main application class.
///
/// This class handles command-line arguments and
/// configuration files.
/// Start the TimeServer executable with the help
/// option (/help on Windows, --help on Unix) for
/// the available command line options.
///
/// To use the sample configuration file (TimeServer.properties),
/// copy the file to the directory where the TimeServer executable
/// resides. If you start the debug version of the TimeServer
/// (TimeServerd[.exe]), you must also create a copy of the configuration
/// file named TimeServerd.properties. In the configuration file, you
/// can specify the port on which the server is listening (default
/// 9911) and the format of the date/time string sent back to the client.
///
/// To test the TimeServer you can use any telnet client (telnet localhost 9911).
{
public:
TimeServer() : _helpRequested(false)
{
}

~TimeServer()
{
}

protected:
void initialize(Application& self)
{
loadConfiguration(); // load default configuration files, if present
ServerApplication::initialize(self);
}

void uninitialize()
{
ServerApplication::uninitialize();
}

void defineOptions(OptionSet& options)
{
ServerApplication::defineOptions(options);

options.addOption(
Option("help", "h", "display help information on command line arguments")
.required(false)
.repeatable(false));
}

void handleOption(const std::string& name, const std::string& value)
{
ServerApplication::handleOption(name, value);

if (name == "help")
_helpRequested = true;
}

void displayHelp()
{
HelpFormatter helpFormatter(options());
helpFormatter.setCommand(commandName());
helpFormatter.setUsage("OPTIONS");
helpFormatter.setHeader("A server application that serves the current date and time.");
helpFormatter.format(std::cout);
}

int main(const std::vector<std::string>& args)
{
if (_helpRequested)
{
displayHelp();
}
else
{
// get parameters from configuration file
unsigned short port = (unsigned short)config().getInt("TimeServer.port", 9911);
std::string format(config().getString("TimeServer.format", DateTimeFormat::ISO8601_FORMAT));

// set-up a server socket
ServerSocket svs(port);
// set-up a TCPServer instance
TCPServer srv(new TimeServerConnectionFactory(format), svs);
// start the TCPServer
srv.start();
// wait for CTRL-C or kill
waitForTerminationRequest();
// Stop the TCPServer
srv.stop();
}
return Application::EXIT_OK;
}

private:
bool _helpRequested;
};


int main(int argc, char** argv)
{
TimeServer app; // 9911
return app.run(argc, argv);
}

start tcpserver.

tcpclient

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//
// TimeClient.cpp
//

#include "Poco/Net/SocketAddress.h"
#include "Poco/Net/StreamSocket.h"
#include <iostream>

using Poco::Net::SocketAddress;
using Poco::Net::StreamSocket;

int main(int argc, char** argv)
{
SocketAddress sa("127.0.0.1",9911);
StreamSocket ss(sa);
int n;
char buffer[256];

//n = 11 , s[0,1,2,....10] = hello world s[11]='\0'
n = ss.receiveBytes(buffer, sizeof(buffer)-1);
buffer[n] = '\0';

std::cout << buffer << std::endl;
std::cout << n << std::endl;
}

start tcpclient to receive data from tcpserver.

telnet as tcpclient

install telnet on windows by contron panel.

1
telnet localhost 9911

Reference

History

  • 20180125: created.