user2457516
user2457516

Reputation:

Including shared library via symlink results in undefined reference

I am trying to use a shared library (to which I don't know the source code). However I struggle with linking it into my project. The library contains an API for a camera driver, which is pretty much a bunch of functions thrown together (as far as I can see there is no structure).

The library (and two symlinks to it) are located in /usr/lib and are called

libueye_api64.so.4.72 - the library
libueye_api.so.1      - a symlink pointing to above library
libueye_api.so        - another symlink pointing to libueye_api64.so.4.72

there also is a header file located in /usr/include named ueye.h which is the header file for the library (at least I assume that).

Using the simple example mwe.cpp

#include "ueye.h"
int main()
{
    int device_count = 0;
    int error_value = is_GetNumberOfCameras(&device_count);
    return 0;
}

which I tried to compile (successful) and link, I got the following:

~/Documents/mwe$ g++ -I/usr/include -c mwe.cpp
~/Documents/mwe$ g++ -L/usr/lib -lueye_api mwe.o -o test
mwe.o: In function `main':
mwe.cpp:(.text+0x17): undefined reference to `is_GetNumberOfCameras'
collect2: error: ld returned 1 exit status

Which should mean that either is_GetNumberOfCameras is not implemented in the library or I have some scoping issue. In any way the linker can't find an implementation for this function (which is part of the API according to the documentation). I further dumped the list of all symbols in the .so using

readelf -Ws /usr/lib/libueye_api64.so.4.72

which has the symbol I am looking for:

980: 00000000003372b0     5 FUNC    GLOBAL DEFAULT   12 is_GetNumberOfCameras

This makes me wonder why I can't find it. Am I including the wrong library? I tried compiling with ueye_api64 but this would just return cannot find library. So, what am I missing?

Edit: I should also mention, that I am doing this under Linux (Ubuntu 14.04) using gcc, which you probably figured out by now.

Upvotes: 2

Views: 1153

Answers (1)

Edgar Rokjān
Edgar Rokjān

Reputation: 17483

Try to change:

g++ -L/usr/lib -lueye_api mwe.o -o test

To:

g++ mwe.o -o test -L/usr/lib -lueye_api

You can look at this SO discussion to understand why the order is important. The accepted answer gives a great explanation.

The main idea is that the linker checks library to resolve currently unresolved symbols only once when it meets this library in the list of options.

But all options are processed consequently.

So if you put -lueye_api before mwe.o linker doesn't know about mwe.o and, of course, it doesn't try to resolve anything (in fact, he hasn't any symbols to resolve).

From the other side, if you put -lueye_api after mwe.o linker firstly add all unresolved symbols from mwe.oto the list of unresolved symbols and after that resolves all of them using ueye_api library successfully.

Finally, this is another good discussion that will be helpful for you.

Upvotes: 4

Related Questions