I'm working with a device that provides conio.h, conio.c. In my c++ code, whenever I call getch(), I get these errors
/usr/bin/ld: CMakeFiles/hello.dir/main.cpp.o: undefined reference to symbol '_Z5getchv'
//usr/lib/libPhantomIOLib42.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
CMakeFiles/hello.dir/build.make:96: recipe for target 'hello' failed
make[2]: *** [hello] Error 1
CMakeFiles/Makefile2:82: recipe for target 'CMakeFiles/hello.dir/all' failed
make[1]: *** [CMakeFiles/hello.dir/all] Error 2
Makefile:90: recipe for target 'all' failed
make: *** [all] Error 2
I know conio is not standard but it seems the company addresses the OS issue by
#if defined(WIN32)
#include <windows.h>
#include <conio.h>
#else
#include "conio.h"
#include <string.h"
#endif
where conio.h is
#ifndef __CONIO_H_
#define __CONIO_H_
#ifdef _cplusplus
extern "C" {
#endif // _cplusplus
int _kbhit();
int getch();
#ifdef _cplusplus
}
#endif // _cplusplus
#endif // __CONIO_H
and conio.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <termios.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
static struct termios term_attribs, term_attribs_old;
static void restore_term(void)
{
if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attribs_old) < 0)
{
perror("tcsetattr: ");
exit(-1);
}
}
int _kbhit()
{
static int initialized;
fd_set rfds;
struct timeval tv;
int retcode;
if(!initialized)
{
if(tcgetattr(STDIN_FILENO, &term_attribs) < 0)
{
perror("tcgetattr: ");
exit(-1);
}
term_attribs_old = term_attribs;
if(atexit(restore_term))
{
perror("atexit: ");
exit(-1);
}
term_attribs.c_lflag &= ~(ECHO | ICANON | ISIG | IEXTEN);
term_attribs.c_iflag &= ~(IXON | BRKINT | INPCK | ICRNL | ISTRIP);
term_attribs.c_cflag &= ~(CSIZE | PARENB);
term_attribs.c_cflag |= CS8;
term_attribs.c_cc[VTIME] = 0;
term_attribs.c_cc[VMIN] = 0;
if(tcsetattr(STDIN_FILENO, TCSANOW, &term_attribs) < 0)
{
perror("tcsetattr: ");
exit(-1);
}
initialized = 1;
}
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
memset(&tv, 0, sizeof(tv));
retcode = select(1, &rfds, NULL, NULL, &tv);
if(retcode == -1 && errno == EINTR)
{
return 0;
}
else if(retcode < 0)
{
perror("select: ");
exit(-1);
}
else if(FD_ISSET(STDIN_FILENO, &rfds))
{
return retcode;
}
return 0;
}
int getch()
{
fd_set rfds;
int retcode;
FD_ZERO(&rfds);
FD_SET(STDIN_FILENO, &rfds);
retcode = select(1, &rfds, NULL, NULL, NULL);
if(retcode == -1 && errno == EINTR)
{
return 0;
}
else if(retcode < 0)
{
perror("select: ");
exit(-1);
}
return getchar();
}
My CMakeLists.txt is
cmake_minimum_required(VERSION 3.10)
project(project2 VERSION 0.1.0 LANGUAGES CXX)
set(CMAKE_CXX_FLAGS "-W -O2 -DNDEBUG -Dlinux")
add_executable(hello main.cpp conio.c conio.h)
target_link_libraries(hello HDU HD rt ncurses stdc++ m)
From the conio., I see _cplusplus which should address the c++ code. Why there an error and to fix it? My OS is ubuntu 18.04. One of the Makefiles provided by the company is
CXX=g++
CXXFLAGS+=-W -fexceptions -O2 -DNDEBUG -Dlinux -Iinclude
LIBS = -lHDU -lHD -lrt -lncurses -lstdc++ -lm
TARGET=ServoLoopDutyCycle
HDRS=include/StatsSampler.h
SRCS=src/ServoLoopDutyCycle.cpp \
src/StatsSampler.cpp \
src/conio.c
OBJS=$(patsubst %.cpp,%.o,$(patsubst %.c,%.o,$(SRCS)))
.PHONY: all
all: $(TARGET)
$(TARGET): $(SRCS)
$(CXX) $(CXXFLAGS) -o $# $(SRCS) $(LIBS)
.PHONY: clean
clean:
-rm -f $(OBJS) $(TARGET)
Related
I am trying to use the function GetAdapterIdentifier but for some reason I keep on getting an error
g++ main.cpp -ld3d9 -ld3dcompiler -lgdi32 -static -static-libstdc++ -o output
main.cpp: In function 'int main()':
main.cpp:22:59: error: cannot call member function 'virtual HRESULT IDirect3D9::GetAdapterIdentifier(UINT, DWORD, D3DADAPTER_IDENTIFIER9*)' without object
22 | HRESULT hResult = IDirect3D9::GetAdapterIdentifier(x ,xWord, &pIdentifier);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
make: *** [Makefile:7: build] Error 1
This is my main.cpp file very simple yet still got an error
#include <iostream>
#include <d3d9.h>
#include <D3D9Types.h>
#include <tchar.h>
int main(void)
{
UINT x;
DWORD xWord;
D3DADAPTER_IDENTIFIER9 pIdentifier;
HRESULT hResult = IDirect3D9::GetAdapterIdentifier(x ,xWord, &pIdentifier);
return 0;
}
I am using a Makefile to compile the main file
CC = g++
FILES = main.cpp
OUT_EXE = output
INCLUDES = -ld3d9 -ld3dcompiler -lgdi32 -static -static-libstdc++
build:$(FILES)
$(CC) $(FILES) $(INCLUDES) -o $(OUT_EXE)
Found this blog that helped me get to this answer
#include <iostream>
#include <d3d9.h>
#include <D3D9Types.h>
#include <tchar.h>
#include <string.h>
LPDIRECT3D9 g_pDirect3D = NULL;
LPDIRECT3DDEVICE9 g_pDirect3D_Device = NULL;
int main(void)
{
UINT x = 0; // Ordinal number that denotes the display adapter.
DWORD xWord = 0 ;
D3DADAPTER_IDENTIFIER9 pIdentifier ;
g_pDirect3D = Direct3DCreate9(D3D_SDK_VERSION);
HRESULT hResult = g_pDirect3D->GetAdapterIdentifier(x, xWord, &pIdentifier);
if (hResult == D3D_OK)
std::cout << "Successfully created DirectX handle " << std::endl;
else
std::cout << "Failed to create DirectX handle" << std::endl;
return 0;
}
Direct3DCreate9 creates a handle to call the functions from
I use Raspberry Pi 3 Zero, put the sudo apt-get install libi2c-dev package, compile g ++ (Raspbian 8.3.0-6 + rpi1) 8.3.0 Why am I getting these errors?
Command:
g++ -c main.cpp
g++ -c HX.cpp
g++ main.o HX.o -lm -li2c -pthread -lpigpio -lrt -lwiringPi
HX.cpp: In constructor ‘HX::HX(int32_t)’:
HX.cpp:34:17: error: ‘i2c_smbus_read_byte_data’ was not declared in this scope
int8_t power = i2c_smbus_read_byte_data(device_id, MPU_POWER1);
^~~~~~~~~~~~~~~~~~~~~~~~
HX.cpp:34:17: note: suggested alternative: ‘i2c_smbus_ioctl_data’
int8_t power = i2c_smbus_read_byte_data(device_id, MPU_POWER1);
^~~~~~~~~~~~~~~~~~~~~~~~
i2c_smbus_ioctl_data
HX.cpp:35:2: error: ‘i2c_smbus_write_byte_data’ was not declared in this scope
i2c_smbus_write_byte_data(device_id, MPU_POWER1, ~(1 << 6) & power);
^~~~~~~~~~~~~~~~~~~~~~~~~
HX.cpp:35:2: note: suggested alternative: ‘i2c_smbus_ioctl_data’
i2c_smbus_write_byte_data(device_id, MPU_POWER1, ~(1 << 6) & power);
^~~~~~~~~~~~~~~~~~~~~~~~~
i2c_smbus_ioctl_data
HX.cpp
#include "HX.hpp"
HX::HX(int32_t id){
device_id = id;
if(device_id < 0){
fprintf(stderr, "Error number: %d\nString error: %s\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
if(ioctl(device_id, I2C_SLAVE, MPU_ADDRESS) < 0){
fprintf(stderr, "Error number: %d\nString error: %s\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
int8_t power = i2c_smbus_read_byte_data(device_id, MPU_POWER1);
i2c_smbus_write_byte_data(device_id, MPU_POWER1, ~(1 << 6) & power);
fprintf(stdout, "%sMPU9250 initialize successful\n", KGRN);
}
HX::~HX(){
close(device_id);
}
I included few headers in HX.cpp, but I used extern "C"
extern "C" {
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <i2c/smbus.h>
}
It's working)
I'm running into some issues compiling and I'm not sure why. I get a multiple definition error for a few things, however, as far as I'm aware, I only define them once. I'm confused as to why this is happening and where these definitions are happening and why its not working. I'm not that familiar with C++ so I'm not sure what I'm doing wrong here and would appreciate some assistance.
make
/usr/bin/g++ -c -o object/author.o src/author.cpp -g -I./include
/usr/bin/g++ -o ---- object/connection_manager.o object/author.o. object/control_header_lib.o object/network_util.o object/main.o object/control_handler.o -g -I./include
object/main.o:(.bss+0x4): multiple definition of `control_socket'
object/connection_manager.o:(.bss+0x104): first defined here
object/main.o: In function `main':
/home/Documents/---/src/main.cpp:9: multiple definition of `router_socket'
object/connection_manager.o:/home/Documents/---/src. /connection_manager.cpp:35: first defined here
object/main.o: In function `main':
/home/Documents/---/src/main.cpp:9: multiple definition of `data_socket'
object/connection_manager.o:/home/Documents/---/src. /connection_manager.cpp:35: first defined here
object/control_handler.o:(.bss+0x0): multiple definition of `CONTROL_PORT'
object/main.o:/home/Documents/---/src/main.cpp:9: first defined here
object/connection_manager.o: In function `main_loop()':
/home/Documents/---/src/connection_manager.cpp:33: undefined reference to `new_control_conn(int)'
/home/Documents/---/src/connection_manager.cpp:54: undefined reference to `isControl(int)'
/home/Documents/---/src/connection_manager.cpp:56: undefined reference to `control_recv_hook(int)'
collect2: error: ld returned 1 exit status
Makefile:19: recipe for target '----' failed
make: *** [----] Error 1
main.cpp
#include "../include/global.h"
#include "../include/connection_manager.h"
using namespace std;
int sockfd;
int main(int argc, char **argv)
{
if(argc != 2){
ERROR("Incorrect number of args...\n");
}
printf("control port: %d\n", atoi(argv[1]));
sscanf(argv[1], "%" SCNu16, &CONTROL_PORT);
init();
return 0;
}
global.h
#ifndef GLOBAL_H_
#define GLOBAL_H_
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#define ERROR(err_msg) {perror(err_msg); exit(EXIT_FAILURE);}
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#endif
connection_manager.cpp
#include <sys/select.h>
#include "../include/connection_manager.h"
#include "../include/global.h"
#include "../include/control_handler.h"
int control_socket, router_socket, data_socket;
void init()
{
control_socket = create_control_sock();
}
connection_manager.h
#ifndef CONNECTION_MANAGER_H_
#define CONNECTION_MANAGER_H_
void init();
#endif
control_handler.cpp
#include <sys/socket.h>
#include <netinet/in.h>
#include <strings.h>
#include <sys/queue.h>
#include <unistd.h>
#include <string.h>
#include <list>
#include "../include/global.h"
#include "../include/network_util.h"
#include "../include/control_header_lib.h"
#include "../include/author.h"
#ifndef PACKET_USING_STRUCT
#define CNTRL_CONTROL_CODE_OFFSET 0x04
#define CNTRL_PAYLOAD_LEN_OFFSET 0x06
#endif
struct ControlConn // linked list for active control connections
{
int sockfd;
// ..
}*connection, *conn_temp;
std::list<ControlConn> control_conn_list;
int create_control_sock()
{
int sock;
struct sockaddr_in control_addr;
socklen_t addrlen = sizeof(control_addr);
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock < 0){
ERROR("Failed to create socket...\n");
}
bzero(&control_addr, addrlen);
control_addr.sin_family = AF_INET;
control_addr.sin_addr.s_addr = htonl(INADDR_ANY);
control_addr.sin_port = htons(CONTROL_PORT);
if (bind(sock, (struct sockaddr *)&control_addr, addrlen) < 0){
ERROR("Bind failed...");
}
if (listen(sock, 5) < 0){
ERROR("Listen failed...");
}
return sock;
}
control_handler.h
#ifndef CONTROL_HANDLER_H_
#define CONTROL_HANDLER_H_
int create_control_sock();
int new_control_conn(int sock_index);
bool isControl(int sock_index);
bool control_recv_hook(int sock_index);
#endif
In header file you need to just declare variable:
extern uint16_t CONTROL_PORT;
Then in corresponding cpp (global.cpp) file you should define it:
uint16_t CONTROL_PORT;
I have following code which use dlopen and dlsym.
main.cpp
#include <stdio.h>
#include <dlfcn.h>
int main(int argc,char** argv) {
void* handler;
handler = dlopen("./libsql.so",RTLD_LAZY);
if(handler){
int (*insert)(const char*);
char* error=NULL;
dlerror(); /* Clear any existing error */
*(void **) (&insert) = dlsym(handler, "openAndInsert");
if ((error = dlerror()) == NULL) {
(*insert)(argv[1]);
}
else {
printf("Error in dlsym\n");
}
}
else {
printf("dlopen error\n");
}
return 0;
}
Compile command:g++ main.cpp -ldl
libsql.cpp
#include <sqlite3.h>
#include <string.h>
#include <stdio.h>
#include "libsql.h"
int openAndInsert(const char* sql) {
sqlite3 *db;
sqlite3_stmt *stmt;
sqlite3_initialize();
int rc = sqlite3_open("./database.db", &db);
if(rc==0){
rc = sqlite3_prepare(db, sql, strlen(sql), &stmt, NULL);
if(rc==0) {
if(sqlite3_step(stmt)){
printf("Done\n");
}
else {
printf("execute error\n");
}
sqlite3_finalize(stmt);
}
else {
printf("prepare error\n");
}
sqlite3_close(db);
}
else {
printf("open error\n");
}
sqlite3_shutdown();
}
libsql.h
#ifndef LIBSQL_H_
#define LIBSQL_H_
#ifdef __cplusplus
extern "C" {
#endif
int openAndInsert(const char* sql);
#ifdef __cplusplus
}
#endif
#endif
compile command:g++ -fPIC -shared -o libsql.so libsql.cpp
Now when I run application I get error as below.
./a.out: symbol lookup error: ./libsql.so: undefined symbol: sqlite3_initialize
But libsqlite3 already installed and works fine with other programm.
When I used below command to generate my *.so file Its works fine.
g++ -fPIC -shared -o libsql.so libsql.cpp -lsqlite3
I want to use a personal "pthread_self" function. I want to rewrite the "pthread_self()" and, at the final, call to the real "pthread_self".
is it possible in C/C++?
Example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
pthread_t pthread_self(void)
{
// Do something else.....
// ...
// And finally call to de real pthread_self():
return ::pthread_self(); // This doesn't work
}
main()
{
printf("\nThis is my main thread: %lu\n", pthread_self());
}
the code seems to be C89 without a return type for main. So I suggest you remove the :: operator infront of pthread_self() in the function pthread_self(void) and recompile.
Also call your pthread_self() by some other name such as pthread_self_2(void)
Will it be allowed to overload pthread_self() with a dummy variable (never used)?
pthread_t pthread_self( bool )
{
// Do something else.....
// ...
// And finally call to de real pthread_self():
printf( "%s\n", __PRETTY_FUNCTION__ );
return ::pthread_self(); // This doesn't work
}
int main()
{
printf( "%s\n", __PRETTY_FUNCTION__ );
pthread_self( false );
printf( "%s\n", __PRETTY_FUNCTION__ );
}
produces
$ g++ test.cpp -lpthread
$ ./a.out
int main()
pthread_t pthread_self(bool)
int main()
$
Two other approaches might be:
Write a function my_pthread_self(), use it everywhere, and have it call real pthread_self()
Have a macro PTHREAD_SELF which calls your wrapper which internally calls real pthread_self()
The following is a bit hacky but should work in C. Put the following in a header which you would have to include before or instead of <pthread.h> (but never after pthread.h):
pthread_t _pthread_self(void);
#define pthread_self _pthread_self
And in the corresponding .c file:
#include <pthread>
#include "wrapper.h"
#undef pthread_self // undo the hack locally
pthread_t _pthread_self(void)
{
// Do something else.....
// ...
// And finally call to the real pthread_self():
return pthread_self();
}
Now, when you write pthread_self in some other file than that .c file, it expands to your wrapper function. Within the .c file above, since this hack is not done, the call within the wrapper will call the library function.
This should give you some ideas. If you control the linking of your executable, you don't need to use LD_PRELOAD.
Thanks to all of you.
Based mainly on these two links Intercepting Arbitrary Functions on... and Tutorial: Function Interposition in Linux show by #Carl Norum and #Arkadyi, I show you a possible solution:
I have two source files and a Makefile:
mipthread_self.C:
#include <stdio.h>
#include <pthread.h>
#if defined (__STDC__) || defined (__cplusplus) || defined (c__plusplus)
#if defined (__cplusplus) || defined (c__plusplus)
extern "C" {
#endif
pthread_t __real_pthread_self();
pthread_t __wrap_pthread_self(void)
{
printf("This is mipthread_self %lu\n", __real_pthread_self());
return __real_pthread_self();
}
#if defined (__cplusplus) || defined (c__plusplus)
}
#endif
#endif
test.C:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void* start_function(void* value)
{
printf("Thread start function is running for: %u\n", (unsigned int)pthread_self());
sleep(5);
pthread_exit(value);
}
int main()
{
int res;
pthread_t thread1, thread2;
void* threadReturnValue;
res = pthread_create(&thread1, NULL, start_function, (void*)"thread-one");
if (res != 0) {
perror("Creation of thread failed");
exit(EXIT_FAILURE);
}
printf("Thread1 created with id: %u\n", (unsigned int)thread1);
res = pthread_create(&thread2, NULL, start_function, (void*)"thread-two");
if (res != 0) {
perror("Creation of thread failed");
exit(EXIT_FAILURE);
}
printf("Thread2 created with id: %u\n", (unsigned int)thread2);
res = pthread_join(thread1, &threadReturnValue);
if (res != 0) {
perror("Joining of thread failed");
exit(EXIT_FAILURE);
}
printf("%s joined.\n", (char*)threadReturnValue);
res = pthread_join(thread2, &threadReturnValue);
if (res != 0) {
perror("Joining of thread failed");
exit(EXIT_FAILURE);
}
printf("%s joined.\n", (char*)threadReturnValue);
return 0;
}
And the Makefile:
BIN=test
CFLAGS=-g -m32 -fPIC -Wall $(DEFINES)
TIPO=-m32
PWD=`pwd`
DIR_OBJ=$(PWD)
DIR_BIN=$(DIR_OBJ)
INCLUDES=
LD_LIBRARIES=-L$(DIR_OBJ) -lmipthread -Xlinker --wrap -Xlinker pthread_self -lpthread -lstdc++
$(BIN): libmipthread.a
#echo ""
#echo "Se va a generar el binario $#"
#echo ""
gcc $(CFLAGS) test.C -o $(DIR_BIN)/$# $(LD_LIBRARIES)
libmipthread.a: mipthread_self.o
ar crv $(DIR_OBJ)/$# $(DIR_OBJ)/$<
mipthread_self.o: mipthread_self.C
gcc $(CFLAGS) -c ${PWD}/$< -o $(DIR_OBJ)/$# $(INCLUDES)
clean:
rm $(DIR_OBJ)/*.o
rm $(DIR_OBJ)/*.a
rm $(DIR_OBJ)/test