Error compiling a cpp file (ros) - c++

I'm working on knowrob package and I already wrote my ontology(XML file) with Protege.
If I parse the owl.file and send some queries I have right answers.
Now my problem is to make a cpp to parse my xml file.
I already read something about json_prolog to send queries from my program to knowrob but is too muddler(http://www.knowrob.org/doc/interact_with_knowrob_via_ros).
I create my launch file and it works,later when i try to compile this cpp file:
#include <string>
#include <ros/ros.h>
#include <json_prolog/prolog.h>
using namespace std;
using namespace json_prolog;
int main(int argc, char *argv[])
{
ros::init(argc, argv, "test_json_prolog");
Prolog pl;
PrologQueryProxy bdgs = pl.query("member(A, [1, 2, 3, 4]), B = ['x', A], C = foo(bar, A, B)");
for(PrologQueryProxy::iterator it=bdgs.begin();
it != bdgs.end(); it++)
{
PrologBindings bdg = *it;
cout << "Found solution: " << (bool)(it == bdgs.end()) << endl;
cout << "A = "<< bdg["A"] << endl;
cout << "B = " << bdg["B"] << endl;
cout << "C = " << bdg["C"] << endl;
}
return 0;
}code here
I have the error:
/tmp/cccLQk3H.o:test_json_prolog.cpp:function main: error: undefined reference to 'ros::init(int&, char**, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int)'
and other similar error about the undefined reference.
CMakelist :
cmake_minimum_required(VERSION 2.8.3)
project(json_prolog)
find_package(catkin REQUIRED rosjava_build_tools roscpp rospy json_prolog_msgs)
catkin_rosjava_setup(installApp publishMavenJavaPublicationToMavenRepository writeClasspath)
install(DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_GLOBAL_MAVEN_DESTINATION}/org/knowrob/${PROJECT_NAME}/
DESTINATION ${CATKIN_GLOBAL_MAVEN_DESTINATION}/org/knowrob/${PROJECT_NAME})
catkin_package(INCLUDE_DIRS include LIBRARIES json_prolog CATKIN_DEPENDS json_prolog_msgs )
# find SWI Prolog libraries
include(FindPkgConfig)
pkg_check_modules(SWIPL REQUIRED swipl)
include_directories(${SWIPL_INCLUDE_DIRS})
link_directories(${SWIPL_LIBRARY_DIRS})
# export Python libraries
catkin_python_setup()
# C++ client library
include_directories(include ${catkin_INCLUDE_DIRS})
find_package(PkgConfig)
pkg_check_modules(JSON_GLIB REQUIRED json-glib-1.0)
add_definitions(${JSON_GLIB_CFLAGS})
link_directories(${JSON_GLIB_LIBRARIY_DIRS})
How can I solve it?

You should start investigating with checking if your call to find_package() (you called find_package(), right?) was successful, so change the snippet you added in your question by adding a debug line,
message(STATUS ${catkin_LIBRARIES})
add_executable(test_json_prolog examples/test_json_prolog.cpp)
target_link_libraries(test_json_prolog json_prolog ${catkin_LIBRARIES})
add_dependencies(test_json_prolog ${catkin_EXPORTED_TARGETS})
Call to message should be printing the libraries you meant to link to.
Besides, see this page if you haven't already, http://wiki.ros.org/catkin/CMakeLists.txt. There they mention a custom macro that you MUST call, i.e. catkin_package(). Also the sections 6, 7, and 8 are all linked to your problem I guess.

You can try to compile it directly using g++ compiler.
Please check this answer:
Compile roscpp without ros (using g++)
There a source code is compiled without cmake or catkin_make

Related

Linking external libraries in C++ in Visual Studio Code

Good afternoon! I have a following program in C++, in VS Code. The program reads all data from a table called student. I compile this program with the command g++ retrieveDataFromTable.cpp -I "C:\Program Files\MySQL\MySQL Server 8.0\include" -L "C:\Program Files\MySQL\MySQL Server 8.0\lib" -l mysql -o test, and it perfectly gets compiled. It's my first time that I use an external library in my programs. So, I watched some videos about how linking works, and how to add an external library to our program. Basically, in those videos they used Visual Studio or Codeblocks for adding libraries, but I'm using VS Code. Eventually, I managed to make the program work, but I have some questions. First one is about the way I include header file "mysql.h". I mean it does not look professional. If I were to run this program in other device, of course that would not make any sense. So would anybody like to help me out how I could make it better? My second question is that the program does terminate if I did not have libmysql.dll in my project folder. I'm guessing that it's because I do dynamic linking with the library (please, correct me if I'm wrong). So does anybody know about how I could link this particular library statically? In general, I would really appreciate if anyone would give me some piece of advice about how I could improve this program, and what I should learn to know about these kind of things. Thank you)
#include <iostream>
#include "C:/Program Files/MySQL/MySQL Server 8.0/include/mysql.h"
struct CONNECTION
{
const char *server = "localhost";
const char *user = "root";
const char *password = "password";
const char *database = "project";
};
MYSQL *connection_to_database(CONNECTION connection)
{
MYSQL *newConnection = mysql_init(NULL);
if (!newConnection)
{
std::cout << "Failed to create an object" << std::endl;
std::cout << mysql_error(newConnection) << std::endl;
exit(0);
}
if (!mysql_real_connect(newConnection, connection.server, connection.user,
connection.password, connection.database, 3306, NULL, 0))
{
std::cout << "Failed to connect to database:" << std::endl;
std::cout << mysql_error(newConnection) << std::endl;
exit(0);
}
return newConnection;
}
MYSQL_RES *execute_query(MYSQL *connection, const std::string query)
{
if (mysql_query(connection, query.c_str()))
{
std::cout << "MYSQL query error:\n"
<< mysql_error(connection) << std::endl;
exit(0);
}
return mysql_store_result(connection);
}
int main()
{
CONNECTION id;
MYSQL* connection = connection_to_database(id);
MYSQL_RES* res = execute_query(connection, "SELECT * FROM students");
int rows = mysql_affected_rows(connection);
std::cout << rows << " rows were affected" << std::endl;
int columns = mysql_num_fields(res);
std::cout << columns << " columns in the table" << std::endl;
MYSQL_ROW row;
while((row = mysql_fetch_row(res)))
{
for (int i = 0; i < columns; i++){
std::cout << row[i] << " ";
}
std::cin.get();
}
return 0;
}
I looked some questions but I could not find something useful.
How about using CMake?
You can easily link external libraries into your target executable.
On top of that, is it perfectly supported on vscode by CMake tools extension.
cmake_minimum_required(VERSION 3.25)
project(myProject)
include_directories(${CMAKE_SOURCE_DIR}/include)
link_directories(${CMAKE_SOURCE_DIR}/lib)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} libmysql.so)
Thank you guys for your answers! I managed to solve this problem, but I need to do some research why it actually worked (if you could help me I would really appreciate it). Basically I made three directories: build, include, lib. "include" and "lib" directories I copied from MYSQL Server 8.0 directory. The outputs of cmake are stored in "build" directory. I have the following command in CMakeLists.txt:
cmake_minimum_required(VERSION 3.25)
project(myProject)
include_directories(${CMAKE_SOURCE_DIR}/include)
link_directories(${CMAKE_SOURCE_DIR}/lib)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(${PROJECT_NAME} mysql)
And it builds successfully. HOWEVER (!!!) when I try to run it, it just terminates. So I put libmysql.dll in "build" directory and then it ran. I'm really new to these things guys, and this solution of mine probably is not professional. If you guys could recommend me how to improve this procedure, or how to manage to make the program work without libmysql.dll file, I would really appreciate it.

loading rosbag duration using cpp

I am interested to load contents of rosbag into databse using sqlite and c++.
while including rosbag/view.h and rosbag/bag.h header file in my cpp file in visual studio code I am facing error of no such file or directory
code: ref http://wiki.ros.org/rosbag/Cookbook#C.2B-.2B-
#include <ros/ros.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>
int main(int argc, char **argv)
{
rosbag::Bag bag;
bag.open("input.bag", rosbag::bagmode::Read);
rosbag::View view(bag);
ros::Time bag_begin_time = view.getBeginTime();
ros::Time bag_end_time = view.getEndTime();
std::cout << "ROS bag time: " << (bag_end_time-
bag_begin_time).toSec() << "(s)" << std::endl;
bag.close();
return 0;
}
error:
main.cpp:2:10: fatal error: rosbag/bag.h: No such file or directory
2 | #include <rosbag/bag.h>
| ^~~~~~~~~~~~~~
Issue is resolved by including ros package, directories and libraries in the CmakeLists.txt and executing the code with cmake and make respectively now able to see the rosbag duration.
cmake_minimum_required(VERSION 3.13 FATAL_ERROR)
project(esw2 VERSION 0.0.1 LANGUAGES CXX)
find_package(rosbag REQUIRED)
add_executable(folder_name
file.cpp
)
target_include_directories(bag_reader
PUBLIC
include
${rosbag_INCLUDE_DIRS}
)
target_link_libraries(bag_reader
PRIVATE
${rosbag_LIBRARIES}
stdc++fs
)

SQLException 32104 in OCCI

I am trying to use OCCI to connect my program to an oracle database but I am getting an SQLException 32104 when I try the createEnvironment function.
My code:
#include <OpenXLSX.hpp>
#include <occi.h>
#include <string>
using namespace OpenXLSX;
using namespace oracle::occi;
int main() {
std::string user = "";
std::string pass = "";
std::string conn_str = "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.2.159)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=test)))";
std::cout << "Initializing Database Connection ......" << std::endl;
try {
Environment* env = Environment::createEnvironment(Environment::DEFAULT);
//Connection *conn = env->createConnection(user, pass ,conn_str);
} catch(SQLException &e) {
std::cout << "Error Message: " << e.getErrorCode() << std::endl;
std::cout << e.getMessage() << std::endl;
}
std::cout << "Initializing Database Connection ......";
std::cout << " OK" << std::endl;
XLDocument doc;
doc.open("Template.xlsx");
auto wks = doc.workbook().worksheet("Extruder Data Log");
int row_number = 4;
char column_letter = 'A';
char column_letter2 = 'A';
std::string loc;
loc = column_letter;
loc += std::to_string(4);
wks.cell(loc).value() = "Hello, OpenXLSX!";
doc.save();
//env->terminateConnection(conn);
//Environment::terminateEnvironment(env);
std::cout << "Program Terminated: Press Enter ...";
std::string wait;
std::cin >> wait;
return 0;
}
I am using CMake to compile:
cmake_minimum_required(VERSION 3.15)
project(Atlas)
set(CMAKE_CXX_STANDARD 17)
# Set the build output location to a common directory
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/output)
set(CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/include/lib)
add_subdirectory(OpenXLSX)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/include/OpenXLSX/headers)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/include/OpenXLSX)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/include/OCCI)
link_directories(${CMAKE_PREFIX_PATH})
find_package(OpenXLSX REQUIRED)
find_library(OCCI NAMES oraocci21.lib oci.lib oramysql.lib oraocci21d.lib ociw32.lib)
add_executable(Atlas Atlas.cpp)
target_link_libraries(Atlas OpenXLSX::OpenXLSX)
target_link_libraries(Atlas ${OCCI})
I have the dlls in the output directory where the executable and libraries end up outputting to.
I figure that it should run, but I am getting a Microsoft C++ exception: oracle::occi::SQLException
and on debugging it shows that it is message 32104 which I know means that it cannot get the error.
The Debug window show that it loads the oraocci21.dll but not any of the other OCCI dlls.
If anyone can let me know what I'm doing wrong I would be incredibly grateful since I have scoured the internet trying to figure this out.
EDIT
Figured out this error, I hadn't moved all of the dlls from the instant client. I was only including the dlls that corresponded to the library names.
I included ocijdbc21.dll, orannzsbb.dll, and oraociicus.dll to the folder with my executable and it now runs past the createEnvironment(Environment::DEFAULT) part.
With this edit, though, I am now running into Error 24960 which says that OCI_ATTR_USERNAME is more than length 255 which it is not.
If anyone can help with that please let me know but I hope that anyone else running across this who needs help sees the part about the dlls.
If it helps to answer my question, I am using instant client base 21_3 and sdk 21_3. I am also using MSVC 16 2019 for compilation with C++17 as the version of C++. My Oracle Database is running on 19c and I can connect to it remotely.
So I figured it out.
I was using this command for cmake:
cmake --build . --target ALL_BUILD --config Debug
This release config command should work because I have debugged the program:
cmake --build . --target ALL_BUILD --config Release
For some reason, I can only assume that OCCI did not like my debugger
version or something like that. If someone could please comment on why this happens I would like to learn.

Cmake: How to build custom compiler binary and then use it for some targets?

I need to build a custom C++ compiler binary and then use it for some targets in the project.
What is the best way to do it in modern CMake?
I set a dependency from the compiler target, and it works as expected, but then what, use 'generator expressions' to get the compiler target binary name?
set(CMAKE_CXX_COMPILER ...) -- either it doesn't understand generator expressions or I misuse it somehow.
Is there a way to set the compiler only for specific targets? As I understand, set(CMAKE_CXX_COMPILER) works for current directory and its children.
You can use a toolchain file, which are made to specify cross compilers.
Here's an example I took from the documentation:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_SYSROOT /home/devel/rasp-pi-rootfs)
set(CMAKE_STAGING_PREFIX /home/devel/stage)
set(tools /home/devel/gcc-4.7-linaro-rpi-gnueabihf)
set(CMAKE_C_COMPILER ${tools}/bin/arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/arm-linux-gnueabihf-g++)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
This is okay since it's in a toolchain file. CMake is made to properly handle toolchain files.
You use it by specifying it in the command line arguments:
cmake .. -DCMAKE_TOOLCHAIN_FILE=your_toolchain.cmake
I made an MCVE for a sample application (App/app.cc) with non-C++ source code (App/text.txt) which has to be compiled via intermediate C++ sources.
The sample directory tree:
└┬─ ./
├─── CMakeLists.txt
├─┬─ App/
│ ├─── CMakeLists.txt
│ ├─── app.cc
│ └─── text.txt
└─┬─ Tool/
├─── CMakeLists.txt
└─── tool.cc
The file ./CMakeLists.txt is the main project file (provides the solution for VisualStudio):
project(App)
cmake_minimum_required(VERSION 3.10.0)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_subdirectory(App)
add_subdirectory(Tool)
The source code ./Tool/tool.cc for a build-tool to generate a C++ source and a header out of a text file:
// a sample tool converting a text file to a c++ source
#include <fstream>
#include <iostream>
#include <string>
int main(int argc, char **argv)
{
if (argc < 3) {
std::cerr <<
"ERROR in tool: Missing arguments!\n"
"\n"
"Usage:\n"
"tool TXT_FILE CC_FILE\n";
return -1;
}
std::ifstream fIn(argv[1]);
if (!fIn.good()) {
std::cerr << "ERROR: Cannot open '" << argv[1] << "' for reading!\n";
return -1;
}
const std::string fileH = std::string(argv[2]) + ".h";
std::ofstream fOutH(fileH);
if (!fOutH.good()) {
std::cerr << "ERROR: Cannot open '" << fileH << "' for writing!\n";
return -1;
}
const std::string fileCC = std::string(argv[2]) + ".cc";
std::ofstream fOutCC(fileCC);
if (!fOutCC.good()) {
std::cerr << "ERROR: Cannot open '" << fileCC << "' for writing!\n";
return -1;
}
fOutCC << "#include \"" << fileH << "\"\n\n";
for (std::string buffer; std::getline(fIn, buffer);) {
const size_t i = buffer.find('=');
if (i < buffer.size()) {
fOutH << "extern const char *const " << buffer.substr(0, i) << ";\n";
fOutCC << "const char *const " << buffer.substr(0, i)
<< " = \"" << buffer.substr(i + 1) << "\";\n";
}
}
fOutH.close();
if (!fOutH.good()) {
std::cerr << "ERROR: Couldn't complete writing of '" << fileH << "'!\n";
return -1;
}
fOutCC.close();
if (!fOutCC.good()) {
std::cerr << "ERROR: Couldn't complete writing of '" << fileCC << "'!\n";
return -1;
}
return 0;
}
The file ./Tool/CMakeLists.txt to build the tool:
project(Tool)
add_executable(tool
tool.cc)
set_property(TARGET tool
PROPERTY FOLDER "Tools")
The file ./App/text.txt – a text file which has to be converted to generated sources text.cc and text.h:
text1=Hello World.
text2=Text built with tool -> VC++
The source ./App/app.cc where text.h is included:
// a sample app using an indirect built source file
#include <iostream>
#include "text.h"
int main()
{
std::cout << "text1: '" << text1 << "'\n";
std::cout << "text2: '" << text2 << "'\n";
return 0;
}
Finally, the ./App/CMakeLists.txt which introduces the custom build step:
# custom build step
add_custom_command(
OUTPUT
text.cc text.h
COMMAND
tool "${CMAKE_CURRENT_SOURCE_DIR}/text.txt" text
MAIN_DEPENDENCY
text.txt
DEPENDS
tool
COMMENT
"generate C++ sources from text"
VERBATIM)
# regular C++ build
add_executable(app
app.cc # regular source files
text.cc text.h) # intermediate source files
# add build dir for project to include directories
include_directories(app
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>)
Having DEPENDS tool in add_custom_command and the OUTPUT of add_custom_command in add_executable grants that:
test.txt is listed as source in the VS-project of app
VS-project tool is included into VS-solution App
tool is compiled and linked, and then used to convert test.txt to test.h and test.cc before app is compiled and linked (successfully).
The generated intermediate sources appear in the build directory (don't pollute the source directory). Hence, the build directory has to be set as include path as well. Otherwise, the #include "text.h" (in app.cc) wouldn't work.

Use two different Versions of boost

i try to build a cmake which use two different version of boost. ( I use a framework which only runs with boost 1.55 but my application needs boost 1.57)
My idea was to make 2 Cmake build processes
Application Cmake boost 1.57
cmake_minimum_required (VERSION 2.6)
project (Application)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=auto -std=c++0x ")
set(Boost_DEBUG ON)
set(Boost_NO_SYSTEM_PATHS TRUE)
set(BOOST_ROOT /opt/boost/boost_1_57)
find_package(Boost 1.57 REQUIRED COMPONENTS thread filesystem log system)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
SYSTEM /opt/boost/boost_1_57/include
)
ADD_LIBRARY( AppLib SHARED testVersion.cpp ...)
Framework Cmake boost 1.55
cmake_minimum_required(VERSION 2.8.3)
project(Test)
add_subdirectory(Application)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=auto -std=c++0x ")
set(Boost_NO_SYSTEM_PATHS TRUE)
set(BOOST_ROOT $ENV{BOOST_ROOT})
find_package(Boost 1.55 REQUIRED COMPONENTS thread filesystem log system)
include_directories(
SYSTEM ${Boost_INCLUDE_DIRS}
)
add_executable(test test.cpp)
target_link_libraries( test AppLib )
test.cpp
#include "testVersion.hpp"
int main() {
std::cout << "Main call Using Boost "
<< BOOST_VERSION / 100000 << "." // major version
<< BOOST_VERSION / 100 % 1000 << "." // minior version
<< BOOST_VERSION % 100 // patch level
<< std::endl;
std::cout << "library : " << std::endl;
Version v;
v.callVersion();
}
testVersion
#include "testVersion.hpp"
void Version::callVersion()
{ std::cout << "Using Boost "
<< BOOST_VERSION / 100000 << "." // major version
<< BOOST_VERSION / 100 % 1000 << "." // minior version
<< BOOST_VERSION % 100 // patch level
<< std::endl;
}
testVersion.hpp
#include <boost/version.hpp>
class Version
{
public:
void callVersion();
};
If i do it this way it runs well :
Output:
Main call Using Boost 1.55.0
Using Boost 1.57.0
But when I eliminate the testVersion.cpp file and inline my callVersion I get the output:
Main call Using Boost 1.55.0
library :
Using Boost 1.55.0
because the compiler use for the headers boost 1.55 only when i include boost in the source files he takes 1.57. How i can solve that ? is that possible?
Conclusion:
I need an empty header :
all_boost_includes.hpp
with a all_boost_includes.cpp
#include "boost..."
#include ...
which will just include all boost headers. And then i have to include this header in every header in my application. Is that correct?
This is similar to an precompiled boost header or?
I tried include "boost_headers.hpp" which is empty and has a boost_header.cpp which includes boost versions
I added on my Application cmake
ADD_LIBRARY( AppLib SHARED boost_headers.cpp)
But when i try
#include "precompiled_boost.hpp"
#include <fstream>
#include <iostream>
class Version
{
public:
void callVersion(){
std::cout << "Using Boost "
<< BOOST_VERSION / 100000 << "." // major version
<< BOOST_VERSION / 100 % 1000 << "." // minior version
<< BOOST_VERSION % 100 // patch level
<< std::endl;
}
};
He don't know BOOST_VERSION. What I have to do there ? If i include precompiled_boost.cpp i get the wrong output
1. If you do not inline callVersion
Compiling library compiles code for Version::callVersion within the library. As library uses boost 1.55 Version::callVersion will return 1.55.
2. If you do inline callVersion
Compiling library does not compile code for Version::callVersion within the library, because it will bi inlined! Your Version::callVersion will actually be compiled on the test side. As test uses boost 1.57, Version::callVersion will return 1.57
Conclusion
You should not inline you calls. More, you cannot use classes that refer to any boost in their declarations in both application and library projects that use different versions of boost. If you have to, you should consider creating some proxy objects or functions, so all boost stuff will be encapsulated inside your library.