2

I receive this compilation error when I try to compile my code:

/tmp/cc5InCzw.o: In function `Audiophile::lastfm_session()':
/media/Storage/Source Files/Audiophile/Scrobbling.cc:25: undefined reference to `LASTFM_init(char const*, char const*)'
/media/Storage/Source Files/Audiophile/Scrobbling.cc:27: undefined reference to `LASTFM_login(void*, char const*, char const*)'
/media/Storage/Source Files/Audiophile/Scrobbling.cc:48: undefined reference to `LASTFM_status(void*, char const**, int const**, char const**)'
/media/Storage/Source Files/Audiophile/Scrobbling.cc:51: undefined reference to `LASTFM_track_scrobble(void*, char*, char*, char*, long, unsigned int, unsigned int, unsigned int, _List**)'
/media/Storage/Source Files/Audiophile/Scrobbling.cc:54: undefined reference to `LASTFM_dinit(void*)'
collect2: error: ld returned 1 exit status

I have been trying to compile an audio program I've been making for Linux with the C library liblastfm. Here is the code for the file that holds my function for scrobbling. The username, password and API keys are changed to Xs.

#include "Audiophile.h"                                                            
#include <stdio.h>                                                                 
#include <time.h>                                                                  
#include <stdlib.h>                                                                
#include <string.h>                                                                
#include "clastfm.h"                                                            

void Audiophile::lastfm_session()                                                  
{                                                                                  

  scrobbling = true;                                                               

  void LASTFM_SESSION *s;                                                          

//    LASTFM_ALBUM_INFO *album;                                                    

//    LASTFM_ARTIST_INFO *artist;                                                  

//    LFMList *list = NULL,*i;                                                     


  const char *status = NULL;                                                       

  s = LASTFM_init("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",                             
                    "XXXXXXXXXXXXXXXXXXXXXXXXXXXX");                           

  int rv = LASTFM_login(s,"XXXXXXXXXXXXX","XXXXXXXXXXXXXXXXXX");                        

  if(rv != 0)                                                                      
  {                                                                                
    cout << "\n\nAn error occurred when logining in!\n\n";                      
  }                                                                                

  unsigned int length = ((position_field / 6000000000) / 10000000000);             

  char* title = const_cast<char*>((playing_track.title()).c_str());                 

  char* album = const_cast<char*>((playing_track.album()).c_str());                 

  char* artist = const_cast<char*>((playing_track.artist()).c_str());              

  time_t start_time;                                                               

  time(&start_time);                                                               

  cout << "\n\nstart time: " << start_time << "\n\n";                              

  LASTFM_status(s,&status,NULL,NULL);                                              

  LASTFM_track_scrobble(s, artist, album, title, start_time, length,               
                        0, 0, NULL);                                               


  LASTFM_dinit(s);                                                                 

  scrobbling = false;                                                              

} 

I include -lclastfm in my compile statement. It is this:

g++ -g -Wall main.cc Audiophile_GTK3.cc Menu_GTK3.cc Playlist_GTK3.cc Configuration_GTK3.cc Configuration.cc Audiophile.cc Metadata.cc Scrobbling.cc -std=c++0x -o audiophile `pkg-config --cflags --libs gtkmm-3.0` $(pkg-config --cflags --libs gstreamer-1.0) $(pkg-config --libs --cflags taglib) -lclastfm -lconfig++ -lboost_system -lboost_filesystem

I'm using Arch. I checked /usr/include and clastfm.h is there. I even tried adding clastfm.h to my program's main directory. That didn't work either. I'm using GStreamer 1.24 extensively in my code, which is pure C. Other than having to clarify a few enumerations, it's worked perfectly with g++. Could an enumeration-related issue be the reason those compilation errors are occurring?

I'll provide the github to my code once I update it if that will help. Not knowing how to do version numbering is the only reason it's not updated (yet).

Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328

1 Answers1

0

These are not compiler errors; your C code is compiling just fine. These are linker errors, which indicates your program is not being successfully linked against liblastfm.

I'm assuming you're linking against liblastfm binaries that you downloaded, and not something you are building. The problem is that this library is a "C" ABI library, and you're compiling your application with g++. That means all symbols will be mangled.

The real problem is that the clastfm.h header file needs to have extern "C" wrapping its contents. This tells g++ to not generate external symbol referenes with mangled names for those functions, and instead use plain-old C-style (non-mangled) naming.

You could try modifying your code like this:

extern "C" {
#include "clastfm.h"
}
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • Thank you, but I realize that. I just poorly worded the question. If you look in my compilation statement, which is the third code box, `-lclastfm` is included. – TheWiseNoob Jun 05 '14 at 07:14
  • I'm wondering if they're missing `extern "C"` in their header files, and g++ is mangling the names. EDIT: They are. Try playing with `extern "C"`, as shown in [this answer](http://stackoverflow.com/a/12994075/119527). – Jonathon Reinhart Jun 05 '14 at 07:19
  • Hmm. That's a part of C I am not familiar with, but it seems like a big possibility. I tried adding it to my code, but I seem to not be using it correctly because I get this error: `expected unqualified-id before string constant extern "C" { LASTFM_SESSION *s; }` – TheWiseNoob Jun 05 '14 at 07:31
  • Your edit to the original answer worked like a charm. Thank you, good sir. If I can ever Vote Up, I will undoubtedly come back to this question to do so. – TheWiseNoob Jun 05 '14 at 07:38