This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 2 years ago.
command line input :
g++ sdlm.cpp -IC:\SDL2-2.0.10\include -LC:\SDL2-2.0.10\lib\x64 -lmingw32 -lSDL2main -lSDL2
main file:
#include <iostream>
#include <SDL.h>
using namespace std;
#undef main
bool run=true;
SDL_Surface * image;
SDL_Surface * winsur;
SDL_Event *e ;
SDL_Renderer *ren;
int main(int argc, char* argv[])
{
if(!SDL_Init(SDL_INIT_EVERYTHING))
{
cout<<"working"<<endl;
cout<<SDL_Init(SDL_INIT_EVERYTHING)<<endl;
SDL_Window * win;
SDL_Renderer * ren;
SDL_Surface *sur;
win=SDL_CreateWindow("window",20,20,1280,600,0);
ren=SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
winsur=SDL_GetWindowSurface(win);
if(ren==NULL)
cout<<"failed to render";
SDL_Event *e;
e=new SDL_Event;
bool run=true;
image=SDL_LoadBMP("chessboard.bmp");
if(NULL==image)
{
cout<<"cannot load the surface"<<SDL_GetError()<<endl;
return 0;
}
while(run==true)
{
SDL_PollEvent(e);
if(e->type==SDL_QUIT)
{
break;
}
SDL_BlitSurface(image,NULL,winsur,NULL);
SDL_UpdateWindowSurface(win);
SDL_PumpEvents();
}
cout<<"exited loop";
}
else
{
cout<<"Something is wrong"<<SDL_GetError()<<endl;
cout<<SDL_Init(SDL_INIT_EVERYTHING)<<endl;
}
SDL_FreeSurface(image);
SDL_FreeSurface(winsur);
return 0;
}
I keep getting the Error:-
sdlm.cpp:(.text+0x1f): undefined reference to SDL_Init
sdlm.cpp:(.text+0x5d): undefined reference to SDL_Init
sdlm.cpp:(.text+0xb2): undefined reference to SDL_CreateWindow
sdlm.cpp:(.text+0xd0): undefined reference to SDL_CreateRenderer
[...]
You have a bunch of linker errors. You need to link all the object files you compile together to produce the final executable.
You may want to use a build system like CMake, SCons or GNU Make to express dependencies in your code, rather than trying to do everything by hand. But if you insist on doing it "by hand", remember that compilation of a C++ program consists of several phases; first is preprocessing, then comes compilation, then assembling (usually done as part of the previous phase by your compiler) and then the final phase is linking all the compiled objects together.
You first of all need to check that all the file directories are mentioned in your command. If the error persists, a nifty trick which shouldn't really be used is to take out -l SDL2main and add at the top of your main.cpp the line #define SDL_MAIN_HANDLED. Also, you are mixing 32-bit and 64-bit: -l mingw32 isn't really compatible with ...\lib\x64 if it's actually 64-bit. Choose one system and stick to that.
Related
EDIT: Nearly got the answer, I just dont completely understand it, see last paragraph.
I try to build a shared lua library and use it within a larger project. When calling the script which loads the shared library from shell everything works. However, when I wrap the script within another shell, I get a runtime error when loading the library. Dependent on the script it is just any call to a lua function from c (i.e. lua_pushnumber). Here is a minimal example.
totestlib.cpp:
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
int init(lua_State *L) {
lua_toboolean(L, -1);
return 0;
}
static const struct luaL_Reg testlib[] = {
{"init", init},
{NULL, NULL}
};
extern "C"
int luaopen_libtotestlib(lua_State *L) {
luaL_newlib(L, testlib);
return 1;
}
Compiled with: g++ -shared -fPIC -I./lua-5.4.4/src -L./lua-5.4.4/src totestlib.cpp -o libtotestlib.so
testlib.lua (testing shared library):
testlib.lua
print("start")
testlib = require("libtotestlib")
print("done")
testlib.init(true)
print("called")
Calling the lua script using ./lua-5.4.4/src/lua testlib.lua works. Everything is printed. Wrapping script in the following c++ code does not work:
call_testlib.cpp
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include <unistd.h>
static lua_State *L;
int main(int argc, char *argv[]) {
L = luaL_newstate();
luaL_openlibs(L);
int tmp = luaL_loadfile(L, "testlib.lua");
if(tmp != 0) {
return 1;
}
tmp = lua_pcall(L, 0, 0, 0);
if(tmp != 0) {
printf("error pcall\n");
return 1;
}
}
Compiled with g++ call_testlib.cpp -o ./call_testlib -I./lua-5.4.4/src -L./lua-5.4.4/src -llua it prints "error pcall". If I print the error message on the lua stack, I get:
string error loading module 'libtotestlib' from file './libtotestlib.so':
./libtotestlib.so: undefined symbol: luaL_checkversion_
In this case the undefined symbol is luaL_checkversion_ (which I dont call myself), but with other scripts it is usually the first lua_... function that I call.
I have tried several things to fix this. For example, linking -llua when compiling the shared library, but this does not work (and should not be the problem as calling the script itself works). I also tried to load preload the library from c++ (as done in this question) instead of from lua, but I guess it does not really make a difference and I am getting the same error. I also uninstalled all lua versions from my path to make sure I always use the same version.
What is the difference between calling the script directly from shell and calling it inside a c function? Am I doing something wrong?
EDIT: Nearly got the answer. When using MYCFLAGS= -fPIC when compiling lua I can link lua to the shared library. At least this one works, but does not seem like a good solution to me and does not really answer my question: Why can lua itself (from shell) somehow add these symbols to the library while the wrapped c version can not? Additionally, my program has lua once linked in the shared library and once in the compiled C++ project (not optimal imo).
I am running my simple C++ program in OMNET ++ IDE
My code is as follows
**#include <stdio.h> // for printf
#include <string.h>
#include <SQLAPI.h> // main SQLAPI++ header
//#include <asaAPI.h>
int main(int argc, char* argv[])
{
SAConnection con;
con.setOption( "UseAPI" ) = "DB-Library";
con.setClient( SA_SQLServer_Client );
try
{
con.Connect(
"paper2"
"NADRA",
"",
SA_SQLServer_Client);
printf("We are connected!\n");
// Disconnect is optional
// autodisconnect will occur in destructor if needed
//con.Disconnect();
printf("We are disconnected!\n");
}
catch(SAException &x)
{
// SAConnection::Rollback()
// can also throw an exception
// (if a network error for example),
// we will be ready
try
{
// on error rollback changes
//con.Rollback();
}
catch(SAException &)
{
}
// print error message
printf("%s\n", (const char*)x.ErrText());
}
return 0;
}**
I have already linked all the files but the error that i am getting is as follow
c:/mingw/bin/../lib/gcc/mingw32/6.3.0/../../../../mingw32/bin/ld.exe: cannot find -lC:\SQLAPI\lib\sqlapi.lib
collect2.exe: error: ld returned 1 exit status
Where as the file sqlapi.lib is in the same folder but linker is not able to find it. Can someone tells me about the issue that why compiler is not able to link it .I am using MINGW as a C++ compiler. The screen shot is attached by with the question about the linked filesenter image description here
If you are using -l, then it should be followed by the library name only, so something like:
-lsqlapi
If you want to specify a search path, then:
-lsqlapi -LC:\SQLAPI\lib\
(Usually the path is in Linux mode, so `C:/SQLAPI/lib though).
Then if this doesn't work, you can always force the library to be linked by just using it as another object:
C:/SQLAPI/lib/sqlapi.lib
Note though that gcc doesn't link against Visual Studio static libraries, which sqlapi might (because of the extension being .lib and not .a, but then this may be the export library for a dll).
I follow the instructions for build xerces in linux
./configure
make
make install
But I'm trying to run the first example from Programming Guide
#include <xercesc/util/PlatformUtils.hpp>
// Other include files, declarations, and non-Xerces-C++ initializations.
using namespace xercesc;
int main(int argc, char* argv[])
{
try {
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch) {
// Do your failure processing here
return 1;
}
// Do your actual work with Xerces-C++ here.
XMLPlatformUtils::Terminate();
// Other terminations and cleanup.
return 0;
}
But I'm getting a few errors:
=== Build: Debug in vasprun_xml (compiler: GNU GCC Compiler) ===
vasprun_xml/main.cpp|22|reference to `xercesc_3_1::XMLUni::fgXercescDefaultLocale' not define
vasprun_xml/main.cpp 22reference to `xercesc_3_1::XMLPlatformUtils::Initialize(char const*, char const*, xercesc_3_1::PanicHandler*, xercesc_3_1::MemoryManager*)' not define
How can I solve this issues?
Anon Mail has reason.
The problem is that Code::Blocks not auto detect system dynamic library.
We need go to
Project->Build Options->Linker Settings
and than add the the name of your library (in our case xerces-c-3.1) without lib prefix. Ok and than build and run without erros.
Is like do
g++ -o main main.cpp /path-to-your-lib/src/.libs/libxerces-c-3.1.so
As mentioned in other SO answers I am using the wrapping mechanism of GNU ld to intercept calls to malloc on Linux (see here for an example).
The used linker flag is -Wl,--wrap=malloc and the respective void __wrap_malloc(size_t) is also defined.
This works fine in a test application where all compilation unit are linked into the same binary.
Now, I need to modify a dynamically linked library which is loaded into a main program via dlopen().
Linking the library succeeds, but loading it into the main program fails with undefined symbol: __real_malloc.
Running nm on the library shows that __wrap_malloc is defined but __real_malloc is not.
But, according to man ld and this SO answer, malloc should get replaced with __wrap_malloc and __real_malloc should point to malloc when using this technique.
In the test application, I see that __real_malloc is undefined in the compiled object files but is resolved after getting linked into the executable.
So, why is the symbol resolved in the test application but not in the dynamic library?
In both cases a final link step is performed which should resolve this symbol.
Or is it required to add another library during the link step of the dynamic library in order to get __real_malloc resolved?
Just in case, it is not possible to modify the target application which loads the dynamic library via dlopen.
It should work and only requires slight changes to the code in the question you linked.
testapp.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
typedef void f_t(void);
int main()
{
void* h = dlopen("./malloc_wrapper.so", RTLD_NOW);
if (h == NULL)
{
puts(dlerror());
exit(1);
}
f_t* f = (f_t*)dlsym(h, "test");
if (f == NULL)
{
puts(dlerror());
exit(1);
}
(*f)();
return 0;
}
malloc_wrapper.c
#include <stdlib.h> /* added */
#include <stdio.h>
void *__real_malloc (size_t);
/* This function wraps the real malloc */
void *__wrap_malloc(size_t size)
{
void *lptr = __real_malloc(size);
printf("Malloc: %lu bytes #%p\n", size, lptr);
return lptr;
}
void test(void) /* added */
{
free(malloc(1024));
}
Compile and run.
gcc -Wl,-wrap,malloc -shared -fpic malloc_wrapper.c -o malloc_wrapper.so
gcc testapp.c -o testapp -ldl
./testapp
Malloc: 1024 bytes #0x1d44680
Compiling malloc_wrapper.so like this reproduces the error you describe:
gcc -shared -fpic malloc_wrapper.c -o malloc_wrapper.so
./testapp
./malloc_wrapper.so: undefined symbol: __real_malloc
Perhaps you were using wrap when compiling and linking the executable instead of the shared object?
I'm trying to use libreDWG to open and understand some dwg files. I have installed it and at least got some of the test programs to run (even if they seg fault later on). Anyway, I have included a small header file in my project very similar to the simple example found here https://github.com/h4ck3rm1k3/libredwg/blob/master/examples/load_dwg.c There seems to be a general problem with data types (at least in the way I'm compiling it) meaning I've added a few casts of form (char*) to number of variables which previously trying to automatically convert (void*) and (unsigned char*) to type (char*) and got rid of those compiler complaints. But even still when I compile it like so
g++ xxx.c++ -L/opt/local/lib/ -lredwg -o program_name
I get the following error:
Undefined symbols for architecture x86_64:
"dwg_read_file(char*, _dwg_struct*)", referenced from:
load_dwg(char*)in ccN6HUqz.o
"dwg_free(_dwg_struct*)", referenced from:
load_dwg(char*)in ccN6HUqz.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
I'm not sure what to do, I've fixed any problems in the source the compiler complains about and am linking to the relevant libraries with -lredwg (right? I haven't missed any?). My header file is just to test the functionality and looks like:
#include "suffix.c"
#include <dwg.h>
plan floor_plan;//temporary data structure defined elsewhere for now
void
add_line(double x1, double y1, double x2, double y2)
{
line_in temp;
temp.start.x=x1;
temp.start.y=y1;
temp.end.x=x2;
temp.end.y=y2;
floor_plan.lines.push_back(temp);
std::cout<<"LINE: :"<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<std::endl;
}
void
add_circle(double x, double y, double R)
{
// Yet to do
}
void
add_text(double x, double y, char *txt)
{
// Make something with that
}
int
load_dwg(char *filename)
{
unsigned int i;
int success;
Dwg_Data dwg;
dwg.num_objects = 0;
success = dwg_read_file(filename, &dwg);
for (i = 0; i < dwg.num_objects; i++)
{
Dwg_Entity_LINE *line;
Dwg_Entity_CIRCLE *circle;
Dwg_Entity_TEXT *text;
switch (dwg.object[i].type)
{
case DWG_TYPE_LINE:
line = dwg.object[i].tio.entity->tio.LINE;
add_line(line->start.x, line->end.x, line->start.y, line->end.y);
break;
case DWG_TYPE_CIRCLE:
circle = dwg.object[i].tio.entity->tio.CIRCLE;
add_circle(circle->center.x, circle->center.y, circle->radius);
break;
case DWG_TYPE_TEXT:
text = dwg.object[i].tio.entity->tio.TEXT;
add_text(text->insertion_pt.x, text->insertion_pt.y, (char*) text->text_value);
break;
}
}
dwg_free(&dwg);
return success;
}
What am I doing wrong? I believe libredwg is written in c. Is this the problem?
It seems that you are trying to link against a 32 bit library when you're on a 64 bit platform, like in this answer. Solution is to download (or build yourself from source) a 64 bit version of libredwg. Or alternatively add the "-m32" flag to your g++ command line - to build your whole app as a 32 bit executable.
EDIT : as you have found out, the problem is actually caused by trying to link C++ code with a C library without the following at the top / bottom of your code :
#ifdef __cplusplus
extern "C" {
#endif
// ... source code here
#ifdef __cplusplus
}
#endif
Basically this tells the compiler not to do C++ name-mangling - switching name mangling off allows linking between C and C++