0%

Part-1: Ubuntu

install

1
2
3
4
sudo apt-get install mysql-server
# root,xxx

mysql -uroot -pxxx

allow remote access

change bind-address

1
2
3
cd /etc/mysql
grep -r 'bind-address' .
./mysql.conf.d/mysqld.cnf:bind-address = 127.0.0.1

change bind-address to 0.0.0.0

1
2
3
4
5
6
7
8
vim ./mysql.conf.d/mysqld.cnf
bind-address = 0.0.0.0

# or
sed -i 's/127.0.0.1/0.0.0.0/g' /etc/mysql/mysql.conf.d/mysqld.cnf

# restart
service mysql restart

grant users

1
2
mysql> grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
mysql> flush privileges;

check for users.

1
2
3
4
5
6
7
8
9
10
11
12
mysql> use mysql;
mysql> select user,host from user;
+------------------+-----------+
| user | host |
+------------------+-----------+
| root | % |
| debian-sys-maint | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+-----------+
5 rows in set (0.00 sec)

OK. Now we can access mysql from remote machine.

Test connection

1
mysql -uroot -p123456 -h 192.168.0.130

Part-2: Windows

install mysql server 5.7

OK

allow remote access

grant users

1
2
3
4
5
6
7
8
9
10
11
mysql> grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
mysql> flush privileges;
```

#### close fireware

close fireware and allow 3306 tcp connection.

### Test connection
```bash
mysql -uroot -p123456 -h 192.168.0.130

or by mysql client.

Reference

History

  • 20180124: created.
  • 20180308: add windows part.

Guide

create table

1
2
3
4
5
CREATE TABLE IF NOT EXISTS `camera` (\
`id` int(11) NOT NULL AUTO_INCREMENT,\
`camera_id` tinyint(4) UNSIGNED NOT NULL,\
`image` longblob NOT NULL,\
`create_time` datetime NOT NULL)

camera.Image of type in c++.

1
std::shared_ptr<char> Image;

insert

sql

1
INSERT INTO camera(camera_id, image) VALUES(? , ? );

code

1
2
3
4
5
6
7
8
9
10
11
12
13
struct membuf : std::streambuf {
membuf(char* base, std::size_t n) {
this->setg(base, base, base + n);
}
};

// get blob istream
char *buffer = camera.Image.get();
size_t size = camera.ImageLength;
membuf mbuf(buffer, size);
std::istream blob(&mbuf); // must be local variable

pstmt->setBlob(6, &blob);

select

sql

1
SELECT id, camera_id, image FROM camera;

code

1
2
3
4
5
std::istream *blob = res->getBlob("image");
size_t size = res->getUInt("image_length");
auto ptr_buffer = Util::get_buffer_from_stream(blob, size);

camera.Image = ptr_buffer;

Reference

History

  • 20180123: created.

Guide

for only storing seconds time_t in mysql with c++, see guide to store time_t with mysql cpp connector in c++.

fractional second part

From Mysql 5.6.4 then on,date,datetime,timestamp support fractional second part (fsp), with up to microseconds (6 digits) precision:

create table

To define a column that includes a fractional seconds part, use the syntax type_name(fsp), where type_name is TIME, DATETIME, or TIMESTAMP, and fsp is the fractional seconds precision. For example:

1
CREATE TABLE t1 (t TIME(3), dt DATETIME(6));

The fsp value, if given, must be in the range 0 to 6, by default is 0.

rounding

Inserting a TIME, DATE, or TIMESTAMP value with a fractional seconds part into a column of the same type but having fewer fractional digits results in rounding, as shown in this example:

use time format YYYY-MM-DD HH:MM:SS[.fraction]

insert

1
2
3
4
5
6
7
use mydb;

DROP TABLE IF EXISTS fractest ;
CREATE TABLE fractest( c1 TIME(2), c2 DATETIME(3), c3 TIMESTAMP(6) );

INSERT INTO fractest
VALUES ('17:51:04.777666', '2014-09-08 17:51:04.777666', '2014-09-08 17:51:04.777666');

select

1
2
3
4
5
6
7
mysql> select * from fractest;
+-------------+-------------------------+----------------------------+
| c1 | c2 | c3 |
+-------------+-------------------------+----------------------------+
| 17:51:04.78 | 2014-09-08 17:51:04.778 | 2014-09-08 17:51:04.777666 |
+-------------+-------------------------+----------------------------+
1 row in set (0.00 sec)

No warning or error is given when such rounding occurs.

how to generate fsp time

Functions that take temporal arguments accept values with fractional seconds. Return values from temporal functions include fractional seconds as appropriate.

For example, NOW() with no argument returns the current date and time with no fractional part, but takes an optional argument from 0 to 6 to specify that the return value includes a fractional seconds part of that many digits.

now() or now(6)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql> select now();
+---------------------+
| now() |
+---------------------+
| 2018-01-22 20:58:31 |
+---------------------+
1 row in set (0.00 sec)

mysql> select now(6);
+----------------------------+
| now(6) |
+----------------------------+
| 2018-01-22 20:58:37.223305 |
+----------------------------+
1 row in set (0.00 sec)

store and select with c++

table

we use DATETIME(6) in mysql to store fsp.

1
CREATE TABLE fractest( create_time DATETIME(6));

insert

both format are ok to insert to mysql,we use to_iso_extended_string in c++ code to get string 2014-09-08T17:51:04.777668.

sql

1
2
3
4
#std::string to_iso_string(ptime)         : YYYYMMDDTHHMMSS,fffffffff      20180908T175104.777668
#std::string to_iso_extended_string(ptime): YYYY-MM-DDTHH:MM:SS,fffffffff 2014-09-08T17:51:04.77766

INSERT INTO fractest VALUES ('2014-09-08T17:51:04.777668');

code

1
2
3
# 2014-09-08T17:51:04.777668
std::string iso_extended_string = boost::posix_time::to_iso_extended_string(camera.CreateTime);
pstmt->setString(1, iso_string);

select

we need to select datetime as string, because we must keep fsp,we use concat("",create_time) as create_time to get string time 2014-09-08 17:51:04.777668, and then process with c++ to get boost ptime.

sql

1
2
3
4
5
# select datetime as string 
# (1) concat("",create_time) as create_time [we can have fsp]
# (2) DATE_FORMAT(create_time,'%Y-%m-%d %h:%m:%s') AS create_time [we can not have fsp]

select id, create_time,concat("",create_time) as create_time from camera where id = 1;

code

1
2
3
std::string mysql_string = res->getString("create_time");
// 2014-09-08 17:51:04.777668 ===> 2014-09-08T17:51:04.777668
camera.CreateTime = Util::from_mysql_string(mysql_string);

different datetime string

filename_string 20180118_111501_208797 
iso_string      20180118T111501.208797  ===> from_iso_string

mysql_string           2014-09-08 17:51:04.777668
ios_extended_string    2014-09-08T17:51:04.777668  ===> from_iso_extended_string

Reference

History

  • 20180122: created.
  • 20180214: add store and select with c++.

Guide

create table

1
2
3
4
CREATE TABLE IF NOT EXISTS `camera` (\
`id` int(11) NOT NULL AUTO_INCREMENT,\
`camera_id` tinyint(4) UNSIGNED NOT NULL,\
`create_time` datetime NOT NULL)

camera.CreateTime of type in c++.

1
time_t CreateTime;

time_t can at most contain seconds, if we want to get millisecond or microsecond, we can use boost.date_time.
see ref: using boost.date_time to get time in millisecond microsecond level

in sql, we use FROM_UNIXTIME and UNIX_TIMESTAMP to insert and select time_t value.

insert

sql

1
INSERT INTO camera(camera_id,create_time) VALUES ( ?,FROM_UNIXTIME(?) );

code

1
pstmt->setUInt64(2, camera.CreateTime); // unix_ts(integer) ===>mysql_ts(string)

select

sql

1
SELECT id,camera_id,UNIX_TIMESTAMP(create_time) as unix_ts FROM camera;

code

1
camera.CreateTime = res->getUInt64("unix_ts");

Reference

History

  • 20180122: created.

Compile

1
2
3
4
5
6
7
8
9
10
11
sudo apt-get install build-essential
wget http://www.cmake.org/files/v3.2/cmake-3.2.2.tar.gz
tar xf cmake-3.2.2.tar.gz
cd cmake-3.2.2
./configure
make && make install


which cmake
#/usr/local/bin/cmake
cmake --version

or by apt-get -y install cmake

User defined cmake

  • FindXXX.cmake in CMAKE_MODULE_PATH
  • xxx-config.cmake in CMAKE_PREFIX_PATH

cmake default package

FindXXX.cmake

  1. use find_package to find default package with name XXX

  2. and cmake file C:\Program Files\CMake\share\cmake-3.10\Modules\FindXXX.cmake

  3. use ${XXX_INCLUDE_DIRS} in include, and ${XXX_LIBRARIES} in libraries

usage

1
2
3
4
5
6
7
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})

find_package(Boost 1.5.8 REQUIRED COMPONENTS date_time system filesystem)
include_directories(${Boost_INCLUDE_DIRS})

target_link_libraries(demo ${GTEST_LIBRARIES} ${Boost_LIBRARIES})

user-defined package

xxx-config.cmake

both names are ok.

  • xxx-config.cmake
  • XXXConfig.cmake, e.g. OpenCVConfig.cmake

mysqlcppconn-config.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Name: <Name>Config.cmake  or <lower name>-config.cmake
# mysqlcppconn-config.cmake or MYSQLCPPCONNConfig.cmake
# similar to OpenCVConfig.cmake

# Tips for MYSQLCPPCONN_ROOT_DIR
# use "C:/Program Files/MySQL/Connector.C++ 1.1", otherwise cmake-gui can not auto find include and library

set(MYSQLCPPCONN_FOUND TRUE) # auto
set(MYSQLCPPCONN_ROOT_DIR "C:/Program Files/MySQL/Connector.C++ 1.1")

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})

halcon-config.cmake

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# halcon-config.cmake or HALCONConfig.cmake  

set(HALCON_FOUND TRUE) # auto
set(HALCON_ROOT_DIR E:/git/car/windows/lib/halcon)

find_path(HALCON_INCLUDE_DIR NAMES halconcpp/HalconCpp.h PATHS "${HALCON_ROOT_DIR}/include")
mark_as_advanced(HALCON_INCLUDE_DIR) # show entry in cmake-gui

find_library(HALCON_LIBRARY NAMES halconcpp.lib PATHS "${HALCON_ROOT_DIR}/lib/x64-win64")
mark_as_advanced(HALCON_LIBRARY) # show entry in cmake-gui

# use xxx_INCLUDE_DIRS and xxx_LIBRARIES in CMakeLists.txt
set(HALCON_INCLUDE_DIRS ${HALCON_INCLUDE_DIR} )
set(HALCON_LIBRARIES ${HALCON_LIBRARY} )

message( "halcon-config.cmake " ${HALCON_ROOT_DIR})

usage

1
2
3
4
5
6
7
find_package(HALCON REQUIRED) # user-defined
include_directories(${HALCON_INCLUDE_DIRS})

find_package(MYSQLCPPCONN REQUIRED) # user-defined
include_directories(${MYSQLCPPCONN_INCLUDE_DIRS})

target_link_libraries(demo ${HALCON_LIBRARIES} ${MYSQLCPPCONN_LIBRARIES})

cmake-gui entry

  1. start cmake-gui, and at first,we should set
  • HALCON_DIR = E:/git/car/share/cmake-3.10/Modules
  • MYSQLCPPCONN_DIR = E:/git/car/share/cmake-3.10/Modules
  1. then configure
  • HALCON_INCLUDE_DIR and HALCON_LIBRARY will be found.
  • MYSQLCPPCONN_INCLUDE_DIR and MYSQLCPPCONN_LIBRARY will be found.

cmake-gui user defined entry

Advanced

execute_process

CMakeLists.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
execute_process(
COMMAND bash "-c" "echo -n hello | sed 's/hello/world/;'"
OUTPUT_VARIABLE VARIABLE
)
MESSAGE( [Main] " VARIABLE = ${VARIABLE}") # world

execute_process(
COMMAND bash "-c" "echo -n $(uname -p)"
OUTPUT_VARIABLE ARCH
)
MESSAGE( [Main] " ARCH = ${ARCH}") # aarch64 x86_64

# glib header only
set(GLIB_INCLUDE_DIRS "/usr/include/glib-2.0/") # glib.h
set(GLIBCONFIG_INCLUDE_DIRS "/usr/lib/${ARCH}-linux-gnu/glib-2.0/include/") # glibconfig.h
MESSAGE( [Main] " GLIB_INCLUDE_DIRS = ${GLIB_INCLUDE_DIRS}")
MESSAGE( [Main] " GLIBCONFIG_INCLUDE_DIRS = ${GLIBCONFIG_INCLUDE_DIRS}")

PIC error

error

1
2
3
/usr/bin/ld: /usr/local/lib/libdlib.a(test_for_odr_violations.cpp.o): relocation R_X86_64_32 against `.bss' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/libdlib.a: error adding symbols: Bad value
collect2: error: ld returned 1 exit status

solution

1
set(CMAKE_BUILD_TYPE "Release") # release

Reference

History

  • 20180122: created.

Series

Guide

Tips

we’d better to use SSD to compile source code instead HDD. So put source code in C folder on windows.
use multiple processor to compile with /MP options.

prepare

software

download

1
2
3
wget https://www.vtk.org/files/release/8.1/VTK-8.1.0.zip
wget https://www.vtk.org/files/release/8.1/VTKData-8.1.0.zip
wget https://github.com/PointCloudLibrary/pcl/archive/pcl-1.8.1.zip

version

window: 10
qt: 5.7.1
qmake: 3.0 based on Qt 5.7.1
qtcreator: 4.2.0 based on Qt 5.7.1

qt-vs-tools: 2.2.1 
cmake/gui: 3.10.0

vtk: 8.1.0 (source)
vtk data: 8.1.0
pcl: 1.8.1 (source)

$ qmake -v
QMake version 3.0
Using Qt version 5.7.1 in C:/Qt/Qt5.7.1/5.7/msvc2015_64/lib

$ qtcreator -version
Qt Creator 4.2.0 based on Qt 5.7.1

$ cmake -version
cmake version 3.10.0

install vs2015

skip.

configure vs2015 with admin

when we compile pcl by vs2015 and install to folder C:/Program Files/PCL , we need administrative priviledges.
follow steps:

cmd+r 
regeidt
HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers

# new string entry
key: C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe
value: ~ RUNASADMIN

vs2015 regedit for runasadmin

install qt

install qt to path C:\Qt\Qt5.7.1

add the following to system path.

C:\Qt\Qt5.7.1\5.7\msvc2015_64\bin
C:\Qt\Qt5.7.1\Tools\QtCreator\bin

install qt-vs-tools

online install by vs2015

start vs2015, install Qt Visual Sutido Tools by:

Tools---> Extensions and Update... ---> online search qt ---> install Qt Visual Sutido Tools ---> OK

restart vs2015 and new menu Qt VS Tools will be added to VS Main menu.

offline install by vsix
wget https://mirrors.tuna.tsinghua.edu.cn/qt/archive/vsaddin/qt-vs-tools-msvc2015-2.1.1.vsix

double click qt-vs-tools-msvc2015-2.1.1.vsix and install.

configure qt for vs

follow steps

Qt VS Tools ---> Qt Options ---> Add name and path

Add qt path for vs2015 so that we can find %PATH%\bin\qmake.exe

Name: Qt 5.7.1
Path: C:\Qt\Qt5.7.1\5.7\msvc2015_64\

qt options

new qt project from vs

start vs2015, and new Qt Gui Application.

new qt gui application

Compile and run first qt program.
Success.

install pcl third parties

install pcl by installer

install pcl to C:\Program Files\PCL 1.8.1\

choose to install OpenNI2 to C:\Program Files\PCL 1.8.1\3rdParty\OpenNI2\

this process will add 4 system env.

PCL_ROOT          C:\Program Files\PCL 1.8.1
OPENNI2_INCLUDE64 C:\Program Files\PCL 1.8.1\3rdParty\OpenNI2\Include\
OPENNI2_LIB64     C:\Program Files\PCL 1.8.1\3rdParty\OpenNI2\Lib\ 
OPENNI2_REDIST64  C:\Program Files\PCL 1.8.1\3rdParty\OpenNI2\Redist\

configure env

add env to Path.

%PCL_ROOT\bin
%PCL_ROOT%\3rdParty\FLANN\bin
%PCL_ROOT%\3rdParty\OpenNI2\Redist
%PCL_ROOT%\3rdParty\OpenNI2\Tools
%PCL_ROOT%\3rdParty\Qhull\bin
%PCL_ROOT%\3rdParty\VTK\bin

copy winpap package

copy winpap to C:\Program Files\PCL 1.8.1\3rdParty\, and 3rdParty folder looks like this:

$ ls -al

total 16
drwxr-xr-x 1 zunli 197609 0 1月  11 12:47 ./
drwxr-xr-x 1 zunli 197609 0 1月  11 08:03 ../
drwxr-xr-x 1 zunli 197609 0 1月  11 08:02 Boost/
drwxr-xr-x 1 zunli 197609 0 1月  11 08:01 Eigen/
drwxr-xr-x 1 zunli 197609 0 1月  11 08:02 FLANN/
drwxr-xr-x 1 zunli 197609 0 1月  11 08:04 OpenNI2/
drwxr-xr-x 1 zunli 197609 0 1月  11 08:02 Qhull/
drwxr-xr-x 1 zunli 197609 0 1月  11 08:03 VTK/
drwxr-xr-x 1 zunli 197609 0 1月  11 12:47 winpcap/

compile vtk

download vtk and data

1
2
wget https://www.vtk.org/files/release/8.1/VTK-8.1.0.zip
wget https://www.vtk.org/files/release/8.1/VTKData-8.1.0.zip

configure source

we need to compile vtk to replace C:\Program Files\PCL 1.8.1\3rdParty\VTK\

1
2
3
cd c:/compile/VTK-8.1.0
mkdir build && cd build
cmake-gui ..

configure generator to Visual Studio 14 2015 Win64 with options

VTK_Group_Qt  ON
VTK_QT_VERSION     5  # by default 4
VTK_RENDERING_BACKEND OpenGL2 # by default OpenGL
Qt5_DIR  C:/Qt/Qt5.7.1/5.7/msvc2015_64/lib/cmake/Qt5

CMAKE_INSTALL_PREFIX  C:/Program Files/VTK  # by default
BUILD_SHARED_LIBS  ON
CMAKE_CONFIGURATION_TYPES Release # Release
CMAKE_CXX_FLAGS_RELEASE /MD /O2 /Ob2 /DNDEBUG /MP # for multiple processor

unzip VTKData-8.1.0.zip and copy MD5 to VTK-8.1.0/build/ExternalData/Objects/MD5

Detailed steps as follows:

  1. With VTK = 8.1.0:

     VTK_Group_Qt  ON
    

    configure again, and then QT_QMAKE_EXECUTABLE and VTK_QT_VERSION will appear.

  2. we need to change VTK_QT_VERSION from 4 to 5.

     VTK_QT_VERSION     5  # by default 4
    
  3. change VTK_RENDERING_BACKEND from OpenGL to OpenGL2.

     VTK_RENDERING_BACKEND OpenGL2 # by default OpenGL
    
  4. set install path C:\Program Files\VTK\

     CMAKE_INSTALL_PREFIX  C:/Program Files/VTK  
    

    we need write privileges to install to C:\Program Files\VTK\

  5. we should also notice BUILD_SHARED_LIBS

     BUILD_SHARED_LIBS  ON
    
  6. add /MP for multiple processor compile

     CMAKE_CXX_FLAGS_RELEASE /MD /O2 /Ob2 /DNDEBUG /MP # for multiple processor
     
     CMAKE_CXX_MP_FLAG ON
     CMAKE_CXX_MP_NUM_PROCESSORS 8
    
  7. Configure

compile

If everything goes well, then generate VTK.sln.

Open VTK.sln in vs2015 and build with Release X64.

NOTICE: this build process will take about 10 minutes.(10:35-10:45)

install vtk

choose INSTALL and generate , and VTK will be installed to C:\Program Files\VTK\.

Notice for QVTKWidgetPlugin and copy dll and lib to C:\Program Files\VTK\.

  • dll: copy C:\compile\VTK-8.1.0\build\bin\Release\QVTKWidgetPlugin.dll to C:\Program Files\VTK\bin\QVTKWidgetPlugin.dll
  • lib: copy C:\compile\VTK-8.1.0\build\lib\Release\QVTKWidgetPlugin.libto C:\Program Files\VTK\lib\QVTKWidgetPlugin.lib

we should also notice that dll has been copied to C:\Program Files\VTK\plugins\designer\QVTKWidgetPlugin.dll

copy vtk to pcl

copy vtk from C:\Program Files\VTK\ to C:/Program Files/PCL 1.8.1/3rdParty/VTK to replace old one.

install QVTKWidgetPlugin

copy C:\Program Files\VTK\plugins\designer\QVTKWidgetPlugin.dll to
C:\Qt\Qt5.7.1\5.7\msvc2015_64\plugins\designer

start vs2015 again, view mainwindow.ui in Qt Designer.

Now QVTKWidget will occur.

qvtkwidget_in_qt_designer

compile pcl

3rdParty

install pcl to get 3rdparty libraries and copy to proper folder.

  • Boost: C:/Boost/include lib version: 1.64 (auto find by cmake)
  • eigen3: C:/Program Files/Eigen/eigen3, version: 3.3.4 (auto find by cmake)
  • FLANN: C:/Program Files/FLANN/include lib bin (auto find by cmake)
  • OpenNI2: C:/Program Files/OpenNI2/Include Lib Redist (user input)
  • Qhull: C:/Program Files/Qhull/include lib bin (auto find by cmake)
  • winpcap: C:/Program Files/winpcap/Include Lib (user input)

cmake options

OpenNI2 include: C:/Program Files/OpenNI2/Include
OpenNI2 LIBRARY: C:/Program Files/OpenNI2/Lib/OpenNI2.lib

pcap  include: C:/Program Files/winpcap/Include
pcap  library: C:/Program Files/winpcap/Lib/x64/wpcap.lib

configure

1
2
3
cd c:/compile/pcl-1.8.1
mkdir build && cd build
cmake-gui ..

with options

QT_USE_FILE C:/compile/pcl-1.8.1/build/use-qt5.cmake
VTK_DIR  C:/Program Files/VTK/lib/cmake/vtk-8.1
CMAKE_INSTALL_PREFIX  C:/Program Files/PCL 

PCL_SHARED_LIBS       ON
PCL_QT_VERSION        5
PCL_ENABLE_SSE        ON

CMAKE_BUILD_TYPE       Release
CMAKE_CONFIGURATION_TYPES Release
CMAKE_INSTALL_PREFIX  C:/Program Files/PCL
CMAKE_CXX_FLAGS_RELEASE /MD /O2 /Ob2 /DNDEBUG /MP # for multiple processor

Build_visualization ON
Build_apps OFF
Build_examples OFF # error may occur

# Fix zlib and png
zlib include: C:/Program Files/VTK/include/vtk-8.1/vtkzlib
zlib library: C:/Program Files/VTK/lib/vtkzlib-8.1.lib

png include:  C:/Program Files/VTK/include/vtk-8.1/vtkpng
png library:  C:/Program Files/VTK/lib/vtkpng-8.1.lib

configure output

code;arch=compute_53,code=sm_53;-gencode;arch=compute_60,code=sm_60;-gencode;arch=compute_61,code=sm_61
...
Boost version: 1.64.0
Found the following Boost libraries:
  system
  filesystem
  thread
  date_time
  iostreams
  chrono
  atomic
  regex
DOXYGEN_FOUND 
HTML_HELP_COMPILER 
Found CPack generators: NSIS
The following subsystems will be built:
  common
  octree
  io
  kdtree
  search
  sample_consensus
  filters
  2d
  geometry
  features
  ml
  segmentation
  surface
  registration
  keypoints
  tracking
  recognition
  stereo
  tools
The following subsystems will not be built:
  visualization: Disabled manually.
  apps: Disabled: visualization missing.
  outofcore: Requires visualization.
  examples: Code examples are disabled by default.
  people: Requires visualization.
  simulation: Disabled: visualization missing.
  global_tests: No reason
Configuring done

OK.

compile

If everything goes well, then generate PCL.sln

Open PCL.sln in vs2015 and build with Release X64.

NOTICE: this build process will take about 30 minutes.

install pcl

by default install need administrator privilidges to write to C:/Program Files/PCL/.

choose INSTALL and generate , and PCL will be installed to C:/Program Files/PCL.

Example

pcl only

pcd_write.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
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>

int main (int argc, char** argv)
{
pcl::PointCloud<pcl::PointXYZ> cloud;

// Fill in the cloud data
cloud.width = 5;
cloud.height = 1;
cloud.is_dense = false;
cloud.points.resize (cloud.width * cloud.height);

for (size_t i = 0; i < cloud.points.size (); ++i)
{
cloud.points[i].x = 1024 * rand () / (RAND_MAX + 1.0f);
cloud.points[i].y = 1024 * rand () / (RAND_MAX + 1.0f);
cloud.points[i].z = 1024 * rand () / (RAND_MAX + 1.0f);
}

pcl::io::savePCDFileASCII ("test_pcd.pcd", cloud);
std::cerr << "Saved " << cloud.points.size () << " data points to test_pcd.pcd." << std::endl;

for (size_t i = 0; i < cloud.points.size (); ++i)
std::cerr << " " << cloud.points[i].x << " " << cloud.points[i].y << " " << cloud.points[i].z << std::endl;

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
22
23
24
25
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(pcd_write_test)

# 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})

#set(PCL_DIR "/path/to/PCLConfig.cmake")
#find_package(PCL 1.8.1 REQUIRED)
find_package(PCL 1.8.1 REQUIRED COMPONENTS common io)

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

message ([main] "PCL_DIR = ${PCL_DIR}")
message ([main] "PCL_FOUND = ${PCL_FOUND}")
message ([main] "PCL_INCLUDE_DIRS = ${PCL_INCLUDE_DIRS}")
message ([main] "PCL_LIBRARIES = ${PCL_LIBRARIES}")
message ([main] "PCL_COMMON_LIBRARIES = ${PCL_COMMON_LIBRARIES}")
message ([main] "PCL_IO_LIBRARIES = ${PCL_IO_LIBRARIES}")

add_executable(pcd_write_test pcd_write.cpp)
target_link_libraries(pcd_write_test ${PCL_COMMON_LIBRARIES} ${PCL_IO_LIBRARIES})

run demo

compile to pcd_write_test.exe and run, errors may occur:

pcd_write_test.exe: error while loading shared libraries: ?: cannot open shared object file: No such file or directory

we need to find out which dlls are imported by exe.

wget http://www.dependencywalker.com/depends22_x64.zip

Tips: use dependency walker to check which dlls are imported, and then copy dll to exe folder.
copy pcl/bin/*.dll and vtk/bin/*.dll to exe folder.

run exe and output

$ ./pcd_write_test.exe   

Saved 5 data points to test_pcd.pcd.
    1.28125 577.094 197.938
    828.125 599.031 491.375
    358.688 917.438 842.563
    764.5 178.281 879.531
    727.531 525.844 311.281

cat pcd

$ cat test_pcd.pcd    

# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z
SIZE 4 4 4
TYPE F F F
COUNT 1 1 1
WIDTH 5
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 5
DATA ascii
1.28125 577.09375 197.9375
828.125 599.03125 491.375
358.6875 917.4375 842.5625
764.5 178.28125 879.53125
727.53125 525.84375 311.28125

create pcl project with vtk and qt support.

pcl+vtk+qt PointCloud Viewer (RECOMMEND)

This project use QVTKWidgetPlugin to display point cloud data.

  • mainwindow.h
  • mainwindow.cpp
  • mainwindow.ui (Contains QVTKWidgetPlugin)
  • main.cpp
  • CMakeLists.txt

mainwindow.h

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
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

// PCL
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>

typedef pcl::PointXYZRGB PointT;
typedef pcl::PointCloud<PointT> PointCloudT;

// Boost
#include <boost/math/special_functions/round.hpp>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private slots:
void on_pushButtonOK_clicked(); // method1
void pushButtonCancel_clicked(); // method2

private:
Ui::MainWindow *ui;

protected:
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;
PointCloudT::Ptr cloud;

void initCloud();
void initialVtkWidget();

unsigned int red;
unsigned int green;
unsigned int blue;
};

#endif // MAINWINDOW_H

mainwindow.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
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
#include "mainwindow.h"
#include "ui_mainwindow.h"

// qt
#include <QMessageBox>
#include <QFileDialog>

// vtk
//#include <vtkAutoInit.h>
//VTK_MODULE_INIT(vtkRenderingOpenGL2);
//VTK_MODULE_INIT(vtkInteractionStyle);
#include <vtkRenderWindow.h> // must include

// pcl
//#include <pcl/io/ply_io.h>
//#include <pcl/io/pcd_io.h>
//#include <pcl/filters/filter.h>

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle("PCL viewer");

// init point cloud data
initCloud();

// set up the QVTK window
initialVtkWidget();

// connect
connect(ui->pushButtonCancel, SIGNAL(clicked()), this, SLOT(pushButtonCancel_clicked()));

}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::initCloud()
{
// Setup the cloud pointer
cloud.reset(new PointCloudT);
// The number of points in the cloud
cloud->points.resize(200);

// The default color
red = 128;
green = 128;
blue = 128;

// Fill the cloud with some points
for (size_t i = 0; i < cloud->points.size(); ++i)
{
cloud->points[i].x = 1024 * rand() / (RAND_MAX + 1.0f);
cloud->points[i].y = 1024 * rand() / (RAND_MAX + 1.0f);
cloud->points[i].z = 1024 * rand() / (RAND_MAX + 1.0f);

cloud->points[i].r = red;
cloud->points[i].g = green;
cloud->points[i].b = blue;
}
}

void MainWindow::initialVtkWidget()
{
viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));
viewer->addPointCloud(cloud, "cloud");
viewer->resetCamera();

ui->qvtkWidget->SetRenderWindow(viewer->getRenderWindow());
viewer->setupInteractor(ui->qvtkWidget->GetInteractor(), ui->qvtkWidget->GetRenderWindow());
ui->qvtkWidget->update();
}

void MainWindow::on_pushButtonOK_clicked()
{
QString text = ui->lineEditName->text();
QMessageBox::information(this, "OK", text);
ui->pushButtonOK->setText( tr("(OK. click me)") );
}

void MainWindow::pushButtonCancel_clicked()
{
QString text = ui->lineEditName->text();
QMessageBox::information(this, "Cancel", text);
ui->pushButtonCancel->setText( tr("(Cancel.click me)") );
}

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}

mainwindow.ui

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
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>553</width>
<height>372</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QLabel" name="labelName">
<property name="geometry">
<rect>
<x>30</x>
<y>20</y>
<width>67</width>
<height>17</height>
</rect>
</property>
<property name="text">
<string>Name</string>
</property>
</widget>
<widget class="QPushButton" name="pushButtonOK">
<property name="geometry">
<rect>
<x>20</x>
<y>250</y>
<width>99</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>OK</string>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/prefix/images/kezunlin_logo.png</normaloff>:/prefix/images/kezunlin_logo.png</iconset>
</property>
</widget>
<widget class="QLineEdit" name="lineEditName">
<property name="geometry">
<rect>
<x>90</x>
<y>20</y>
<width>71</width>
<height>27</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButtonCancel">
<property name="geometry">
<rect>
<x>330</x>
<y>250</y>
<width>99</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
<widget class="QVTKWidget" name="qvtkWidget">
<property name="geometry">
<rect>
<x>240</x>
<y>10</y>
<width>261</width>
<height>201</height>
</rect>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>553</width>
<height>25</height>
</rect>
</property>
<widget class="QMenu" name="menuHello_MainWIndow">
<property name="title">
<string>File</string>
</property>
<addaction name="separator"/>
<addaction name="actionOpen"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionHelp"/>
</widget>
<addaction name="menuHello_MainWIndow"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionFile">
<property name="text">
<string>Open</string>
</property>
</action>
<action name="actionSave">
<property name="text">
<string>Save</string>
</property>
</action>
<action name="actionExit">
<property name="text">
<string>Exit</string>
</property>
</action>
<action name="actionHelp">
<property name="text">
<string>Help</string>
</property>
</action>
<action name="actionOpen">
<property name="text">
<string>Open</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QVTKWidget</class>
<extends>QWidget</extends>
<header>QVTKWidget.h</header>
</customwidget>
</customwidgets>
<resources>
<include location="resource.qrc"/>
</resources>
<connections/>
</ui>

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
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
cmake_minimum_required(VERSION 2.8.8)

project(point_cloud_viewer)

# 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 includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)

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 )

#==============================================================
# PCL (include qt+vtk)
#==============================================================
# better not use ${PCL_LIBRARIES}, use what we need:
# e.g. ${PCL_COMMON_LIBRARIES} ${PCL_VISUALIZATION_LIBRARIES}

#find_package(PCL 1.8.1 REQUIRED)
find_package(PCL 1.8.1 REQUIRED COMPONENTS common io filters visualization)

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

message ([main] "PCL_DIR = ${PCL_DIR}")
message ([main] "PCL_FOUND = ${PCL_FOUND}")
message ([main] "PCL_INCLUDE_DIRS = ${PCL_INCLUDE_DIRS}")
message ([main] "PCL_LIBRARY_DIRS = ${PCL_LIBRARY_DIRS}")
message ([main] "PCL_LIBRARIES = ${PCL_LIBRARIES}")
message ([main] "PCL_COMMON_LIBRARIES = ${PCL_COMMON_LIBRARIES}")
message ([main] "PCL_IO_LIBRARIES = ${PCL_IO_LIBRARIES}")
message ([main] "PCL_FILTERS_LIBRARIES = ${PCL_FILTERS_LIBRARIES}")
message ([main] "PCL_VISUALIZATION_LIBRARIES = ${PCL_VISUALIZATION_LIBRARIES}")

#==============================================================
# Boost
#==============================================================
set(Boost_USE_RELEASE_LIBS ON)
set(Boost_USE_MULTITHREAD ON)
find_package(Boost 1.5.8 REQUIRED COMPONENTS math_tr1)
#include_directories(${Boost_INCLUDE_DIRS})

#==============================================================
# cpp,ui,resource files
#==============================================================
# cpp files
#aux_source_directory(. SRC_LIST)
set(SRC_LIST
main.cpp
mainwindow.h
mainwindow.cpp
)

# 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

#==============================================================
# generate and link target
#==============================================================
add_executable(${PROJECT_NAME} ${SRC_LIST} ${ui_FILES} ${qrc_FILES})

# link qt libraries
qt5_use_modules(${PROJECT_NAME} Core Widgets OpenGL Xml Gui Sql)

# link vtk and pcl libraries
target_link_libraries(${PROJECT_NAME}
${GLOG_LIBRARIES}

${PCL_COMMON_LIBRARIES}
${PCL_IO_LIBRARIES}
${PCL_FILTERS_LIBRARIES}
${PCL_VISUALIZATION_LIBRARIES}

#${PCL_LIBRARIES} # lead to error when build target (no error now)
)

# test_pcd
add_executable(test_pcd test_pcd.cpp)
target_link_libraries(test_pcd
${PCL_COMMON_LIBRARIES}
${PCL_IO_LIBRARIES}
${PCL_FILTERS_LIBRARIES}
${PCL_VISUALIZATION_LIBRARIES}
)

snapshot

./point_cloud_viewer.exe

Point Cloud Viewer for pcd file

errors

when run example, errors may occur: (which has been fixed by now.)
vtkOutputWindow error: no overide found for 'vtkPolyDataMapper'

fix error

fix pcl min,max conflict with windows.h macro

error

C:\Boost\include\boost-1_64\boost\asio\detail\socket_types.hpp(37):# include <windows.h>
we use boost which includes <windows.h> and import macro min/max.
in pcl, std::numeric_limits<int>::max conflict with min/max.

1
2
3
4
5
template <typename PointT> static std::string
generateHeader (const pcl::PointCloud<PointT> &cloud,
const int nr_points = std::numeric_limits<int>::max());

int m = std::numeric_limits<float>::max();

solution

1
2
3
4
5
6
7
8
9
10
// method(1): put this befor pcl headers
#undef max
#undef min

// method(2):
#define NOMINMAX

// pcl headers
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>

Reference

History

  • 20180112: created.
  • 20180208: add DependencyWalker,add pcl pcd demo, pcl+vtk+qt demo.
  • 20180211: add vs2015 regedit for runasadmin.
  • 20180301: change VTK-8.0.1 to VTK-8.1.0.

Intro

what singleton solve?

from stackoverflow here

Singletons solve one (and only one) problem.

Resource Contention.
If you have some resource that
(1) can only have a single instance, and
(2) you need to manage that single instance,
you need a singleton.

There aren’t many examples. A log file is the big one. You don’t want to just abandon a single log file. You want to flush, sync and close it properly. This is an example of a single shared resource that has to be managed.

It’s rare that you need a singleton. The reason they’re bad is that they feel like a global and they’re a fully paid up member of the GoF Design Patterns book.

When you think you need a global, you’re probably making a terrible design mistake.

local static object

Actually, in C++ preferred way is local static object.

singleton pure

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Singleton
{
private:
Singleton();

public:
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;

static Singleton& instance()
{
static Singleton INSTANCE;
return INSTANCE;
}
};

singleton with shared_ptr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Singleton
{
private:
Singleton();

public:
Singleton(Singleton const&) = delete;
Singleton& operator=(Singleton const&) = delete;

static std::shared_ptr<Singleton> instance()
{
static std::shared_ptr<Singleton> s{new Singleton};
return s;
}
};

singleton usage

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
#define DISALLOW_COPY(TypeName) \
TypeName(const TypeName&)

#define DISALLOW_ASSIGN(TypeName) \
TypeName& operator=(const TypeName&)

#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
TypeName(const TypeName&); \
TypeName& operator=(const TypeName&)

class CSingleton
{
public:
static CSingleton &GetInstance()
{
static CSingleton instance;
return instance;
}
void DoSomething()
{
printf("void CSingleton::DoSomething() called.\n");
}

private:
CSingleton() {};
DISALLOW_COPY_AND_ASSIGN(CSingleton);
};

// usage
CSingleton::GetInstance().DoSomething(); // OK

CSingleton& singleton = CSingleton::GetInstance(); // OK with reference
singleton.DoSomething();

CSingleton singleton = CSingleton::GetInstance(); // ERROR (copy constructor)

Example

config.h

1
2
3
4
5
6
7
8
9
10
11
12
13
#pragma once

class Config
{
public:
static Config& GetInstance(std::string filename="./config.ini");
~Config();

private:
Config(std::string filename);
Config(const Config& ref) {}
Config& operator =(const Config& ref) { return *this; }
};

config.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 "Config.h"

/*
static config instance will only be created once by calling Config::Config,
when program exit,static variable will be destoryed by calling Config::~Config.
*/

Config& Config::GetInstance(std::string filename)
{
static Config instance(filename);
return instance;
}

Config::Config(std::string filename)
{
std::cout << "[LOG] Config::Config count= "<<count << std::endl;
// load config from filename
// ...
}

Config::~Config()
{
std::cout << "[LOG] Config::~Config count= " << count << std::endl;
}

mysqldb.cpp

1
2
3
4
5
6
7
8
void MysqlDb::load_config(std::string filename)
{
this->mysql_connection = Config::GetInstance(filename).MYSQL_CONNECTION;
this->mysql_username = Config::GetInstance(filename).MYSQL_USERNAME;
this->mysql_password = Config::GetInstance(filename).MYSQL_PASSWORD;
this->mysql_database = Config::GetInstance(filename).MYSQL_DATABASE;
this->max_connection_pool_size = Config::GetInstance(filename).MAX_CONNECTION_POOL_SIZE;
}

Reference

History

  • 20180122: created.

Series

Guide

install node

1
wget https://nodejs.org/dist/v8.9.4/node-v8.9.4-x64.msi

start node installer and install node,npm to windows.

1
2
3
4
5
node -v 
v8.9.4

npm -v
5.6.0

install hexo global

1
2
npm install -g cnpm --registry=https://registry.npm.taobao.org
cnpm install -g hexo-cli

clone/create your blog

1
2
git clone git@xxxx/blog.git 
# or create your blog

install hexo packages

1
2
cd blog 
ls package.json

package.json

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
{
"name": "hexo-site",
"version": "0.0.0",
"private": true,
"hexo": {
"version": "3.4.4"
},
"dependencies": {
"hexo": "^3.4.4",
"hexo-abbrlink": "^2.0.5",
"hexo-admin": "^2.3.0",
"hexo-deployer-git": "^0.3.1",
"hexo-generator-archive": "^0.1.5",
"hexo-generator-baidu-sitemap": "^0.1.2",
"hexo-generator-category": "^0.1.3",
"hexo-generator-feed": "^1.2.2",
"hexo-generator-index": "^0.2.1",
"hexo-generator-search": "^2.1.1",
"hexo-generator-searchdb": "^1.0.8",
"hexo-generator-sitemap": "^1.2.0",
"hexo-generator-tag": "^0.2.0",
"hexo-neat": "^1.0.4",
"hexo-renderer-ejs": "^0.3.1",
"hexo-renderer-marked": "^0.3.0",
"hexo-renderer-stylus": "^0.3.3",
"hexo-server": "^0.3.0",
"hexo-wordcount": "^3.0.2"
}
}

install packages

1
2
cnpm install --save
cnpm update --save

start hexo

1
hexo server

and visit

Reference

History

  • 20180122: created.

datetime

no fraction part.

create table

1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE IF NOT EXISTS `camera` (\
`id` int(11) NOT NULL AUTO_INCREMENT,\
`camera_id` tinyint(4) UNSIGNED NOT NULL,\
`create_time` datetime NOT NULL,\
PRIMARY KEY(`id`)\
)\
ENGINE = InnoDB\
DEFAULT CHARACTER SET = utf8 COLLATE = utf8_general_ci\
AUTO_INCREMENT = 0\
ROW_FORMAT = DYNAMIC\
;

camera.CreateTime of type time_t

insert

sql

1
INSERT INTO camera(camera_id,create_time) VALUES ( ?,FROM_UNIXTIME(?) );

code

1
pstmt->setUInt64(2, camera.CreateTime); // unix_ts(integer) ===>mysql_ts(string)

select

sql

1
SELECT id,camera_id,UNIX_TIMESTAMP(create_time) as unix_ts FROM camera;

code

1
camera.CreateTime = res->getUInt64("unix_ts");

datetime(6)

with fraction part: millisecond,microsecond

Reference

History

  • 20180118: created.

Guide

install mysql connector for c++

1
2
3
4
5
6
7
8
9
10
11
12
13
14
sudo apt-get -y install mysql-server

#root,xxxxxx
mysql -uroot -pxxxxxx

sudo apt-get -y install libboost-all-dev

sudo apt-cache search libmysqlcppconn

#libmysqlcppconn-dev - MySQL Connector for C++ (development files)
#libmysqlcppconn7v5 - MySQL Connector for C++ (library)

sudo apt-get -y install libmysqlcppconn-dev
sudo apt-get install libmysqlcppconn7v5

target link with options mysqlcppconn

eg.

1
2
3
4
5
6
target_link_libraries (Backend  
Config
Util
Model
mysqlcppconn
)

mysqlcppconn-config.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 MYSQLCPPCONN
#
# The following variables are optionally searched for defaults
# MYSQLCPPCONN_ROOT_DIR: Base directory where all MYSQLCPPCONN components are found
#
# The following are set after configuration is done:
# MYSQLCPPCONN_FOUND
# MYSQLCPPCONN_INCLUDE_DIRS
# MYSQLCPPCONN_LIBRARIES
# MYSQLCPPCONN_LIBRARYRARY_DIRS

include(FindPackageHandleStandardArgs)

set(MYSQLCPPCONN_ROOT_DIR "" CACHE PATH "Folder contains mysqlcppconn")

if(WIN32)
find_path(MYSQLCPPCONN_INCLUDE_DIR cppconn/driver.h
PATHS ${MYSQLCPPCONN_ROOT_DIR})
else()
find_path(MYSQLCPPCONN_INCLUDE_DIR cppconn/dirver.h
PATHS ${MYSQLCPPCONN_ROOT_DIR})
endif()

if(MSVC)
find_library(MYSQLCPPCONN_LIBRARY_RELEASE mysqlcppconn
PATHS ${MYSQLCPPCONN_ROOT_DIR}
PATH_SUFFIXES Release)

find_library(MYSQLCPPCONN_LIBRARY_DEBUG mysqlcppconn
PATHS ${MYSQLCPPCONN_ROOT_DIR}
PATH_SUFFIXES Debug)

set(MYSQLCPPCONN_LIBRARY optimized ${MYSQLCPPCONN_LIBRARY_RELEASE} debug ${MYSQLCPPCONN_LIBRARY_DEBUG})
else()
find_library(MYSQLCPPCONN_LIBRARY mysqlcppconn
PATHS ${MYSQLCPPCONN_ROOT_DIR}
PATH_SUFFIXES lib lib64)
endif()

find_package_handle_standard_args(MYSQLCPPCONN DEFAULT_MSG MYSQLCPPCONN_INCLUDE_DIR MYSQLCPPCONN_LIBRARY)

if(MYSQLCPPCONN_FOUND)
set(MYSQLCPPCONN_INCLUDE_DIRS ${MYSQLCPPCONN_INCLUDE_DIR})
set(MYSQLCPPCONN_LIBRARIES ${MYSQLCPPCONN_LIBRARY})
message(STATUS "Found mysqlcppconn (include: ${MYSQLCPPCONN_INCLUDE_DIR}, library: ${MYSQLCPPCONN_LIBRARY})")
mark_as_advanced(MYSQLCPPCONN_ROOT_DIR MYSQLCPPCONN_LIBRARY_RELEASE MYSQLCPPCONN_LIBRARY_DEBUG
MYSQLCPPCONN_LIBRARY MYSQLCPPCONN_INCLUDE_DIR)
endif()

CMakeLists.txt

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})

Reference

History

  • 2180118: created.
  • 20180223: add mysqlcppconn-config.cmake.