I just cant see what Im doing wrong here:
Q. Why is my library not being found by g++ when compiling the program with a shared object?
Im trying to include a shared library to my c++ program:
g++ -fpic -c sha.cpp
g++ -shared -o libsha.so sha.o
g++ main.cpp -o main -L. -lsha
where sha.cpp and sha.h are the library files and main.cpp is my program.
Ive tried the same with static library which works find:
g++ -static -c sha.cpp -o libsha.o
ar rcs libsha.a libsha.o
g++ main.cpp -o main -L. -lsha
The platform is cygwin on windows and here is the output:
rob#pc /cygdrive/c/src/a
$ g++ main.cpp -o shatest -L. -lsha
/usr/lib/gcc/i686-pc-cygwin/4.3.4/../../../../i686-pc-cygwin/bin/ld: cannot find -lsha
collect2: ld returned 1 exit status
Ive read all forum posts but the library is in the same folder!
$ ls
libsha.so main.cpp sha.cpp sha.h sha.o
The reason im doing this is that on another platform, a library is being created whereby when one object is called, it works, but the app crashes when the second object is being constructed. Im doing the above as a simple test! (annoyingly not so simple).
source files below:
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "sha.h"
void *thread_one( void *ptr );
void *thread_two( void *ptr );
main()
{
pthread_t thread1, thread2;
int iret1, iret2;
/* Create independent threads each of which will execute function */
iret1 = pthread_create( &thread1, NULL, thread_one, 0);
iret2 = pthread_create( &thread2, NULL, thread_two, 0);
/* Wait till threads are complete before main continues. Unless we */
/* wait we run the risk of executing an exit which will terminate */
/* the process and all threads before the threads have completed. */
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
printf("Thread 1 returns: %d\n",iret1);
printf("Thread 2 returns: %d\n",iret2);
exit(0);
}
void *thread_one( void *ptr )
{
printf("Run thread_one\n");
CObj1 obj;
}
void *thread_two( void *ptr )
{
printf("Run thread_two\n");
CObj2 obj;
}
sha.cpp
#include <stdio.h>
#include <stdlib.h>
#include "sha.h"
CObj1::CObj1()
{
printf("CObj1\n");
a = 10;
printf("CObj1: %d \n", a);
}
CObj2::CObj2()
{
printf("CObj2\n");
a = 10;
printf("CObj2: %d \n", a);
}
sha.h
#ifndef LIB
#define LIB
class CObj1
{
public:
CObj1();
private:
int a;
};
class CObj2
{
public:
CObj2();
private:
int a;
};
#endif
Related
Please help me, How to access run time varibale's data(att) in stub.exe of att variable that is defined in proc.so,
I have created proc.so and linked with attol.exe and stub.exe and
attol.exe updates 'att' variable and stub.exe is accessing 'att' variable and prints att's value.
I have used below commands to compile the code :
g++ -Wall -c attol.cc proc.cc stub.cc
g++ -shared -dynamiclib -fPIC -o libproc.so proc.o -ldl
g++ -rdynamic -o attol.exe attol.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
g++ -rdynamic -o stub.exe stub.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
When i am running both .exe at different terminal then attol.exe showing 'att:4' value but stub.exe is showing incorrect value,
But stub.exe should display '4' value or updated value.
out put attol.exe:
./attol.exe
Value of att is : 4
Enter the value of att :
out put stub.exe:
./stub.exe
Att : 0
----Complete Code Details----
proc.h:
#ifndef __X_H_INCLUDED__
#define __X_H_INCLUDED__
extern int att;
int fun();
#endif
proc.cc:
#include<iostream.h>
#include "proc.h"
int att;
int fun ()
{
att=4;
return 0;
}
Above code is generating proc.o and then this proc.o will converted into proc.so with below commands:
g++ -Wall -c attol.cc proc.cc stub.cc
g++ -shared -dynamiclib -fPIC -o libproc.so proc.o -ldl
attol.cc:
#include <iostream.h>
#include "proc.h"
using namespace std;
int main ()
{
int ch=1;
fun();
cout<<"\n Value of att is : "<<att;
do{
cout<<"\n Enter the value of att : ";
cin>>att;
cout<<"\n Do you want to continue the : ";
cin>>ch;
}while(ch!=0);
return 0;
}
attol.cc file creates attol.exe by using below command
g++ -rdynamic -o attol.exe attol.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
out put:
Value of att is : 4
Enter the value of att :
stub.cc:
#include <iostream.h>
#include <dlfcn.h>
int main ()
{
void *handle;
char *error;
handle = dlopen ("/users/hbharti/DLOPEN/proc/libproc.so", RTLD_LAZY);
if (!handle) {
fputs (dlerror(), stderr);
exit(1);
}
int *att =(int*) dlsym(handle, "att");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
exit(1);
}
cout<<"\n Att : " <<*att;
cout<<"\n " ;
dlclose(handle);
}
stub.cc file creates stub.exe by using below command
g++ -rdynamic -o stub.exe stub.o /users/hbharti/DLOPEN/proc/libproc.so -ldl
Judging by the code, there seems to be a fundamental issue with the core-logic.
A shared-object (*.so) is loaded into the executing process's memory address space.
However it is NOT shared across multiple processes. When 2 or more executables attempt to access the same shared-object (*.so), they both get independent copies of it mapped into their respective memory address spaces.
Data (even globals) within a shared-object (*so) are NOT shared across 2 or more executables.
There is a function in aaa.c
int myadd(int a, int b){
return a+b;
}
and aaa.c was built into a static library using
gcc -c aaa.c -o aaa.o && ar -cr libaaa.a aaa.o
and a shared library using
gcc -c aaa.c -o aaa.o && gcc -shared -fPCI -o libaaa.so aaa.o
Then I wrote a file call.c, and try to call function myadd() in libaaa.so, but failed.
Please give me some advice,
test.c:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("Dual BSD/GPL");
extern int myadd(int a, int b);
static int hello_init(void)
{
int c = 0;
printk(KERN_ALERT "hello,I am Destiny\n");
c = myadd(1, 2);
printk(KERN_ALERT "res is (%d)\n", c);
return 0;
}
static void hello_exit(void)
{
printk(KERN_ALERT "goodbye,kernel\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("Destiny");
MODULE_DESCRIPTION("This is a simple example!\n");
MODULE_ALIAS("A simplest example");
This Makefile will make both c file into call.ko, and it will work. But that's not what I want.
Makefile :
KVERSION = $(shell uname -r)
obj-m = call.o
call-objs = aaa.o test.o
Debug:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
All:Debug
cleanDebug:
make -C /lib/modules/$(KVERSION)/build M=/home/Destiny/myProject/kernel/cbtest/ clean
clean:cleanDebug
installDebug:Debug
rmmod /lib/modules/2.6.18-348.12.1.el5/test/call.ko
/bin/cp call.ko /lib/modules/$(KVERSION)/test/
depmod -a
insmod /lib/modules/2.6.18-348.12.1.el5/test/call.ko
install:installDebug
main.o : defs.h
Ko files are running in kernel space , not user space where application running. Libc or libc++ and so on on are prepared for user space application. So you can not link libc/c++ functions, Just like you cannot link any libc functions in kernel.
I'm fairly new to C++ but this thing has me baffled by any logic. My code is as follows:
#include "stdlib.h"
#include "syslog.h"
#include "unistd.h"
#include "sys/stat.h"
#include "X11/Xlib.h"
#include "cstdio"
void process();
void startTracker();
Display *display;
Window rootWindow;
XEvent xevent;
I have the Xlib header included and if I click on member functions in Eclipse it navigates to the definitions.
int main(int argc, char *argv[])
{
// set logging up
openlog("unison", LOG_CONS|LOG_PID|LOG_NDELAY, LOG_LOCAL1);
syslog(LOG_NOTICE, "Starting Unison Handler");
pid_t pid, sid;
pid = fork();
// fork failed
if (pid < 0) {
exit(EXIT_FAILURE);
}
if (pid > 0) {
exit(EXIT_SUCCESS);
}
umask(0);
sid = setsid();
if (sid < 0) {
exit(EXIT_FAILURE);
}
if (chdir("/") < 0) {
exit(EXIT_FAILURE);
}
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
startTracker();
while (true) {
process();
}
closelog();
return(EXIT_SUCCESS);
}
Then I assign the variables for input selection
void startTracker() {
display = XOpenDisplay(0);
rootWindow = XRootWindow(display, 0);
XSelectInput(display, rootWindow, PointerMotionMask);
}
void process()
{
...but when i add the &event here...
XNextEvent(display, &xevent);
switch (xevent.type) {
case MotionNotify:
syslog(
LOG_NOTICE,
"Mouse position is %dx%d",
xevent.xmotion.x_root, xevent.xmotion.y_root
);
}
}
...the whole thing falls apart.
For some reason passing the xevent as reference throws off the entire Xlib header and gives me this:
00:16:15 **** Incremental Build of configuration Debug for project unisond ****
make all
Building file: ../unisond.cpp
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"unisond.d" -MT"unisond.d" -o "unisond.o" "../unisond.cpp"
Finished building: ../unisond.cpp
Building target: unisond
Invoking: GCC C++ Linker
g++ -o "unisond" ./unisond.o
./unisond.o: In function `startTracker()':
/home/ancarius/workspace/unisond/Debug/../unisond.cpp:97: undefined reference to `XOpenDisplay'
/home/ancarius/workspace/unisond/Debug/../unisond.cpp:98: undefined reference to `XRootWindow'
/home/ancarius/workspace/unisond/Debug/../unisond.cpp:99: undefined reference to `XSelectInput'
./unisond.o: In function `process()':
/home/ancarius/workspace/unisond/Debug/../unisond.cpp:105: undefined reference to `XNextEvent'
collect2: error: ld returned 1 exit status
make: *** [unisond] Error 1
00:16:15 Build Finished (took 159ms)
At the risk of getting downvoted could someone please explain what I've done wrong? I've tried everything I could think of but no luck.
It looks like you are missing the X11 library for linking.
add -lX11 to the g++ invocation.
This provides the steps required.
Right click on Project Folder> Properties> C/C++ Build > Settings > GCC C++ Linker > Libraries > add "X11"
Could someone help me with linking to a shared lib, specifically libzmq, in C++?
all: clean compile
clean:
rm bin *.o -f
compile:
g++ -g -Wall -I/usr/local/include -L/usr/local/lib main.cpp -lzmq -o bin
I've installed libzmq using the following steps:
git clone https://github.com/zeromq/libzmq.git
cd libzmq
./autogen.sh
./configure
make && sudo make install
Here's my main.cpp
#include <iostream>
#include <string>
#include <zmq/zmq.h>
// Required by fork routine
#include <sys/types.h>
#include <unistd.h>
// Required by wait routine
#include <sys/wait.h>
#include <stdlib.h> // Declaration for exit()
#include <cstdio> // printf
using namespace std;
int global_variable = 2;
int main(int argc, char** argv){
const short int FORK_FAILED = -1;
const short int FORK_SUCCESS = 0;
int stack_variable = 20;
pid_t pid;
string status_identifier;
switch (pid = fork()){
case FORK_SUCCESS:
printf("Child changing global and stack variables\n");
global_variable++;
stack_variable++;
break;
case FORK_FAILED:
cerr << "Failed! -- Failed to fork: " << pid << endl;
exit(1);
default:
printf("Child process (pid=%d) created successfully.\n", pid);
wait(0);
break;
}
printf("[pid=%d] Global: %d\n", pid, global_variable);
printf("[pid=%d] Stack: %d\n", pid, stack_variable);
return 0;
}
And, here's the error msg:
bitcycle # ubuntu64vm ~/git/test $ make
rm bin *.o -f
g++ -g -Wall -I/usr/local/include -L/usr/local/lib main.cpp -lzmq -o bin
main.cpp:4:23: fatal error: zmq/zmq.hpp: No such file or directory
compilation terminated.
make: *** [compile] Error 1
The error is pretty straight forward, but I've yet to find a solution. Any ideas?
My goal is to do something like this with multiple child processes.
Update I'm just going to install it system-wide in ubuntu: sudo apt-get install libzmq-dev, and that resolved the issue. It doesn't teach me anything about how to identify a shared lib and header file on disk and link to it... but I guess I can move that to another day.
C++ wrapper for ZeroMQ (zmq.hpp) is no longer part of ZeroMQ. There is no zmq.hpp in current libzmq master or in latest stable 3.2.x.
I'm trying to build these files but it's giving me a multiple definition error.
main.cpp:
#include "SDL/SDL.h"
#include "Core.h"
#include "GameStates.h"
#include "globals.h"
int main(int argc, char** args)
{
if(core.Initilization(640, 480, 32, SDL_SWSURFACE) == -1)
{
SDL_Quit();
}
while(core.desiredstate != core.quit)
{
::currentstate->EventHandling();
::currentstate->Logic();
core.ChangeState();
::currentstate->Render();
::currentstate->Update();
}
SDL_FreeSurface(core.screen);
SDL_Quit();
}
Core.cpp:
#include "Core.h"
#include "GameStates.h"
#include "SDL/SDL.h"
#include "Intro.h"
#include "globals.h"
#include <string>
/* Starts SDL subsystems and sets screen attributes */
bool Core::Initilization(int SCREEN_WIDTH, int SCREEN_HEIGHT, int SCREEN_BPP, int FLAGS)
{
//starts SDL subsystems, returns false upon error
if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
return false;
}
//The screen
screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, FLAGS);
//Returns false if there was an error
if(screen == NULL)
{
return false;
}
SDL_WM_SetCaption("Game", NULL);
return true;
}
/* Loads an image and optimizes it */
SDL_Surface* Core::Load(std::string filename)
{
//original loaded image
SDL_Surface* original = SDL_LoadBMP(filename.c_str());
SDL_Surface* optimized = NULL;
if(original != NULL)
{
//Sets optimized to optimized version of original
optimized = SDL_DisplayFormat(original);
SDL_FreeSurface(original);
}
return optimized;
}
/* Blits surfaces */
void Core::ApplySurface(int x, int y, SDL_Surface* source, SDL_Surface* destination)
{
//holds the x y coordinates
SDL_Rect location;
location.x = x;
location.y = y;
if(destination != NULL)
{
SDL_BlitSurface(source, NULL, destination, &location);
}
}
/* Sets desiredstate to be used in ChangeState(); */
void Core::SetState(int newstate)
{
if(desiredstate != state_null && desiredstate != quit)
{
desiredstate = newstate;
}
}
/* Changes the game state */
void Core::ChangeState()
{
if(desiredstate != state_null && desiredstate != quit)
{
//frees old state memory
delete ::currentstate;
switch(desiredstate)
{
case intro:
//allocates new state memory
::currentstate = new Intro();
break;
}
stateID = desiredstate;
desiredstate = state_null;
}
}
GameStates.h:
#ifndef GAMESTATES_H
#define GAMESTATES_H
class GameStates
{
public:
virtual void EventHandling() = 0;
virtual void Logic() = 0;
virtual void Render() = 0;
virtual void Update() = 0;
};
#endif
Intro.h:
#ifndef INTRO_H
#define INTRO_H
#include "SDL/SDL.h"
#include "GameStates.h"
class Intro : public GameStates
{
private:
SDL_Surface* test;
public:
Intro();
void EventHandling();
void Logic();
void Render();
void Update();
~Intro();
} intro;
#endif
Intro.cpp:
#include "Intro.h"
#include "GameStates.h"
#include "Core.h"
#include "SDL/SDL.h"
Intro::Intro()
{
test = core.Load("test.bmp");
}
void Intro::EventHandling()
{
SDL_Event event;
while(SDL_PollEvent(&event))
{
switch(event.type)
{
case SDL_QUIT:
core.SetState(core.quit);
break;
}
}
}
void Intro::Logic()
{
//to be coded when the program actually builds...
}
void Intro::Render()
{
core.ApplySurface(30, 30, test, core.screen);
}
void Intro::Update()
{
SDL_Flip(core.screen);
}
Intro::~Intro()
{
SDL_FreeSurface(test);
}
globals.h:
#include "GameStates.h"
#include "SDL/SDL.h"
GameStates* currentstate = NULL;
Sorry if the indentation is off; having to put four spaces for it to be seen as a code block messed with it a bit.
Heres the error message:
/tmp/ccWxKsO5.o:(.bss+0x0): multiple definition of `core'
/tmp/cc13Eqmt.o:(.bss+0x0): first defined here
/tmp/ccWxKsO5.o:(.bss+0x20): multiple definition of `currentstate'
/tmp/cc13Eqmt.o:(.bss+0x10): first defined here
/tmp/ccJXxewI.o:(.bss+0x0): multiple definition of `intro'
/tmp/ccWxKsO5.o:(.bss+0x10): first defined here
/tmp/ccJXxewI.o:(.bss+0x10): multiple definition of `core'
/tmp/cc13Eqmt.o:(.bss+0x0): first defined here
collect2: ld returned 1 exit status
Makefile:
OBJS = main.o Intro.o Core.o
CC = g++
DEBUG = -g
CFLAGS = -Wall -c $(DEBUG)
LIBS = -lSDL
game : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o game $(LIBS)
main.o : Core.h GameStates.h globals.h
$(CC) $(CFLAGS) main.cpp $(LIBS)
Core.o : Core.h Core.cpp GameStates.h Intro.h globals.h
$(CC) $(CFLAGS) Core.cpp $(LIBS)
Intro.o : Intro.cpp GameStates.h Core.h
$(CC) $(CFLAGS) Intro.cpp $(LIBS)
The problem isn't your code, it's your build system.
Any sane build system matches the name of the object files to the name of the source files. But you have ccWxKsO5.o and cc13Eqmt.o. What's worse, the build system appears to be trying to link multiple objects generated from the same source (perhaps some were created by an earlier run of the compiler).
tempnam and globbing *.o is not a reasonable way to build C++ programs.
Well, there may be some code problems also. But those will be a thousand times easier to find and fix once the object names in the error messages correlate to source files.
For objects shared between multiple translation units, the rule is: there must be exactly one definition, but you may have multiple declarations.
In practice, this means: put "extern Class object;" in your .h file, and "Class object;" in exactly one of your .CPP files.
For intro, for example, change your Intro.h to:
class Intro : public GameStates
{
... // whatever
};
extern Intro intro;
and add this line to Intro.cpp:
Intro intro;
Similarly for currentstate, in globals.h:
extern GameStates* currentstate;
and in one .CPP (it doesn't matter to the compiler which one):
GateStates* currentstate = NULL;
P.s. Your makefile is broken. You pass -c, which means "don't link" to your link step. Try this:
OBJS = main.o Intro.o Core.o
CC = g++
DEBUG = -g
CFLAGS = -Wall $(DEBUG)
LIBS = -lSDL
game : $(OBJS)
$(CC) $(CFLAGS) $(OBJS) -o game $(LIBS)
main.o : Core.h GameStates.h globals.h
$(CC) -c $(CFLAGS) main.cpp
Core.o : Core.h Core.cpp GameStates.h Intro.h globals.h
$(CC) -c $(CFLAGS) Core.cpp
Intro.o : Intro.cpp GameStates.h Core.h
$(CC) -c $(CFLAGS) Intro.cpp
In globals.h, you must declare currentstate extern. Then create globals.cpp, with the definition (GameStates* currentstate = NULL;). I couldn't find any reference for intro or core in your code, but it's probably the same problem: you can declare global variables as often as you want as long as you declare them extern, and only define them once per resulting binary, in only one translation unit.
Also, you probably want to add a header guard (#ifndef GLOBALS_H ...) to globals.h, just in case you add anything else in there.
put include guards in globals.h
make GameStates* declaration extern
//globals.h
#ifndef _MY_GLOBALS_H_
#define _MY_GLOBALS_H_
#include "GameStates.h"
#include "SDL/SDL.h"
extern GameStates* currentstate;
#endif
//Main.cpp
#include "globals.h"
GameStates* currentState = 0;