"Unresolved reference" errora while doing dynamic Linking of C++.so (shared object)
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
"Unresolved reference" errora while doing dynamic Linking of C++.so (shared object)
I am creating two shared libs that i intend to be dynamically linkable in C and C++, cross platform Linux/Windows/Mac.
As a basic sketch, true for both libs, the lib code is in several .c/.cpp and .h files.
For now, I'll talk about the part that I am actively working on, a lib named Discover, i.e. libdiscover.so.1.0.
First, everything is in a namespace, RemKon_Discover.
The main Discover.cpp defines the methods for the Discover class (declared in Discover.h) and has extern "C' routines that can return pointers to my main c++ object. The call to GetLibraryMainPointer() creates a Discover class object, theMainObject (ok, I win a prize for dumb names) and returns the (non-mangled) pointer to the caller over in my test program. The Discover class itself is declared extern "c" and the tester program #includes "Discover.h".
In the test program, dlopen() correctly opens the lib and dlsym() gets the pointer to theMainObject. However, when I use that pointer in the tester program to access a method (aDiscoverObject->hello(), e.g.) I get compile time errors saying that Discover::hello() in an undefined reference.
./RemKonTester/Debug/RemKonTester.o: In function `main':
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:111: undefined reference to `RemKon_Discover::DiscoverObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:116: undefined reference to `RemKon_Discover::DiscoverObject::SetLogLevel(unsigned int)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:117: undefined reference to `RemKon_Discover::DiscoverObject::hello()'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:118: undefined reference to `RemKon_Discover::DiscoverObject::LocalIpAddress(int)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:122: undefined reference to `RemKon_Discover::DiscoverObject::RegisterCallback(bool (*)(void*), void*)'
/home/wmiller/Projects/Eclipse/./RemKonTester/RemKonTester.cpp:123: undefined reference to `RemKon_Discover::DiscoverObject::Search()'
collect2: ld returned 1 exit status
Question, what am I missing or doing wrong? Notice that the line to link RemKonTester does not have any -l (lowercase -L)'s in it. If they are there I get static linking. That's a no no.
Wes
Last edited by archtoad6; 04-15-2011 at 05:39 AM.
Reason: Move to Programming, preserve 0-reply
The Makefile is not "yours"; it was generated by Eclipse.
There are two possibilities that would explain the undefined reference error(s): 1) You neglected to specify the library that contains the implementation of the unresolved functions (or data objects), or 2) you failed to implement these unresolved functions.
Please recheck your library code to verify the functions are indeed implemented. If all is good, then check your Eclipse project settings.
You might also want to consider learning how to build a project using the command line, perhaps using a Makefile that you have created, before placing all your faith in an IDE.
Note, you do not need to specify -lstdc++, nor -fPIC, for your link flags. For the former, g++ automatically links again the library; for the latter, it is not applicable when linking (should only be used when compiling library source code).
Edit: You have not specified -ledgeio nor -ldiscover in the link flags above.
Last edited by dwhitney67; 04-15-2011 at 06:45 AM.
In the test program, dlopen() correctly opens the lib and dlsym() gets the pointer to theMainObject. However, when I use that pointer in the tester program to access a method (aDiscoverObject->hello(), e.g.) I get compile time errors saying that Discover::hello() in an undefined reference.
Notice that the line to link RemKonTester does not have any -l (lowercase -L)'s in it. If they are there I get static linking. That's a no no.
It sounds like you're expecting to be able to get a pointer to aDiscoverObject from dlsym() and for all its methods to come with it, so you can call them without linking to the library they come from at link-time - well, that's just not possible. When you call object->method(x, y) in C++, what you're really doing is making a call to something like __Znamespace_object_method(object, x, y). The method itself is just a plain function, and if you want to call it, you'll have to be able to see it at link-time or the linker will report an error.
To do what you want to do, you'd have to use dlsym() to get a pointer to the method (which will involve finding the mangled name of the method) and the object, and call something like (*meth)(obj, x, y). Unfortunately, C++'s implementation of how exactly parameters are passed to member functions (or how names are mangled) isn't mandated by any standard - you can find out what a particular implementation does and do that, but if things change your library won't be able to work. And it certainly won't be portable at all.
Bottom line: calling C++ class member functions using dlsym is a no-go area. If you really want to export a C++ API in this way, make wrapper functions with C-style linkage and pass pointers to objects around.
(That's all assuming I've understood what you're trying to do correctly...)
Last edited by JohnGraham; 04-15-2011 at 01:21 PM.
The Makefile is not "yours"; it was generated by Eclipse.
No, it's mine. Eclipse makes Makefile, not makefiles (capitalization). This is my makefile I wrote by hand. The behavior is exactly the same as Eclipse's though.
Quote:
Originally Posted by dwhitney67
Please recheck your library code to verify the functions are indeed implemented. If all is good, then check your Eclipse project settings.
All there. All working is VC++ with dynamic linking.
Edit: You have not specif
Quote:
Originally Posted by dwhitney67
ied -ledgeio nor -ldiscover in the link flags above.
No, adding those cause evewrything to compile, but I get static linking which I DO NOT want. I want to ship object code only.
No, adding those cause evewrything to compile, but I get static linking which I DO NOT want. I want to ship object code only.
How did you achieve static linking? You created two shared-object libraries (and no static libraries), and when you build the executable, I do not see any instruction telling the linker to use -static.
Thus could you please elaborate a little further as to what you meant above?
How did you achieve static linking? You created two shared-object libraries (and no static libraries), and when you build the executable, I do not see any instruction telling the linker to use -static.
Thus could you please elaborate a little further as to what you meant above?
Well, I think you've found my problem from a different angle. Maybe it isn't doing static linking, oly something that fools me into thinking it is.
When I execute my tester program, I see messages from the libraries before I see the tester program start. The init() in one or the other library runs twice (I THINK the loader is seeing that I have two so_init()s and runs the same one twice -- first one it finds maybe? Anyway, only after the so-init() runs (twice) and I get some debug messages from the libraries, do I see the first debug messages from my tester code.
Code:
./Debug/RemKonTester
DEBUGMSG: Discover.so: starting. // Discover.so cited but EdgeIO-Lib.log created
Logfile "EdgeIO_Lib.log" created.
DEBUGMSG: Discover.so: starting. // Got it right here
Logfile "Discover_Lib.log" created.
Logfile "RemKonTester.log" created. // First thing said by tester code. Tester created log obj in global space
DEBUGMSG: Discover.so: starting. // Next four lines follow dlopen()/dlsym() in tester
Logfile "EdgeIO_Lib.log" created.
DEBUGMSG: EdgeIO Object Created.
04/18/11 09:24:51: Library libedgeio.so attached and Version Info retrieved. // Tester msg
anEdgeIoObject.test_int = 980722 Public var in EdgeIO lib
anEdgeIoObject.hello() = EdgeIoObject says hello. // hello() function in EdgeIO lib
DEBUGMSG: Discover.so: starting.
Logfile "Discover_Lib.log" created.
DEBUGMSG: Discover Object Created.
04/18/11 09:24:51: Library libdiscover.so attached and Version Info retrieved.
aDiscoverObject.test_int = 704293
aDiscoverObject.hello() = DiscoverObject says hello.
04/18/11 09:24:51: Discover loglevel set to 4.
Are you still employing the use of dlopen()? If so, is there a particular reason for doing such?
I get the impression from your project that you are merely creating two shared-object libraries, and then linking them with your application so that you can build an executable. You then run the program, and generate some output. How/when this output is produced is still appearing fuzzy in my crystal ball.
Just for grins, here is the most trivial app that employs the use of a shared-object library; perhaps you could play with it before delving into more complex things.
""Unresolved reference" errora while doing dynamic Linking of C++.so (shared object)
Quote:
Originally Posted by JohnGraham
It sounds like you're expecting to be able to get a pointer to aDiscoverObject from dlsym() and for all its methods to come with it, so you can call them without linking to the library they come from at link-time - well, that's just not possible. When you call object->method(x, y) in C++, what you're really doing is making a call to something like __Znamespace_object_method(object, x, y). The method itself is just a plain function, and if you want to call it, you'll have to be able to see it at link-time or the linker will report an error.
Well, yeah that's what I want.
Quote:
Originally Posted by JohnGraham
To do what you want to do, you'd have to use dlsym() to get a pointer to the method (which will involve finding the mangled name of the method) and the object, and call something like (*meth)(obj, x, y). Unfortunately, C++'s implementation of how exactly parameters are passed to member functions (or how names are mangled) isn't mandated by any standard - you can find out what a particular implementation does and do that, but if things change your library won't be able to work. And it certainly won't be portable at all.
Ummmm,
Code:
extern "C"
class xyv
{
...
};
} // end extern "C"
should make the class and its methods 'seeable", right?
Wes
Last edited by micropanther; 04-18-2011 at 09:40 AM.
Reason: Type, forgot code block.
should make the class and its methods 'seeable", right?
What do you think `extern "C"' means? It has nothing to do with visibility - it's all about linkage and name mangling. It bypasses C++'s name mangling (which it needs to support namespaces/classes/overloading) so that functions have C-style linkage. You cannot `extern "C"' a class because you need the name mangling - declaring a class extern "C" will either be ignored by the compiler or generate an error.
Quote:
Quote:
It sounds like you're expecting to be able to get a pointer to aDiscoverObject from dlsym() and for all its methods to come with it, so you can call them without linking to the library they come from at link-time - well, that's just not possible. When you call object->method(x, y) in C++, what you're really doing is making a call to something like __Znamespace_object_method(object, x, y). The method itself is just a plain function, and if you want to call it, you'll have to be able to see it at link-time or the linker will report an error.
Well, yeah that's what I want.
Like I said, just getting a pointer to an object won't "bring" the methods out of a shared library - you'll still have to get pointers to the functions you're calling, and call it with whatever hidden arguments that implementation of C++ expects. This is non-portable for the same reason that you can't use a C++ library that's been compiled with a different compiler to the one you're using for compiling/linking your application - the name mangling and ABI will be different.
Unless you have a specific reason for doing what you want to do using dlopen/dlsym etc. and know (or want to learn) how to export a C++ library through a C API (hint: C can't use classes...), I'd suggest you stick with just plain dynamic linking if you want anything that will work...
Last edited by JohnGraham; 04-18-2011 at 10:08 AM.
Are you still employing the use of dlopen()? If so, is there a particular reason for doing such?
Yes, still using dlopen() and dlsym(). Because I want to ship dynamically linkable, object-code-only libs.
Quote:
Originally Posted by dwhitney67
I get the impression from your project that you are merely creating two shared-object libraries, and then linking them with your application so that you can build an executable. You then run the program, and generate some output. How/when this output is produced is still appearing fuzzy in my crystal ball.
I am creating two Object Code Only libraries, thus they need to be dynamically linkable. They will find (Discover) a class of internet devices we sell then control them (EdgeIO). The libs are just to make it easier for customers to program with/for our hardware. The C++ test program dlopen()s the two libs and invokes their functions. Right now, the tester loads both, but only really uses Discover. The tester registers a callback function that Discover uses to notify the tester where to find a structure of currently found devices. Dead simple stuff.
My concern comes from John Graham's posts that say I can't do what I really want to do. This really worries me since I have exactly what I want for VC++, just not with g++. I don't want an MS linux compiler, but I sure would love some degree of sameness between the two (three -- OS/X?) op syses.
Quote:
Originally Posted by dwhitney67
Just for grins, here is the most trivial app that employs the use of a shared-object library; perhaps you could play with it before delving into more complex things.
Why not. I have, however, done this before and gotten the desired results with both g++ and VC++.
Well, I'm just going to take your word for it. I have gotten whatever it is I am trying to do to work before in a project that compiled for 19 different OS'es including Windows 32 and 64, 9 linuxes and AIX. Maybe someday I'll figure out why one worked and the other doesn't. In the meantime, I am going back to pure C external calls.
I have posted more detail in other replies if you care to read them.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.