-2

This question maybe have been asked before. I could not find it to the best of my searches.

I'm trying to link libpfm4.5.0 in my code. The header file that I'm using is the following: perf_util.h

Here is the link to download libpfm4.5.0.

Does it matter where exactly I include the header file?

Here is a snippet of my code:

#include "matrix.h"
#include "perf_util.h"

int read_counts(int pid, int app_num){
    int ret, i, num_fds = 0, grp, group_fd;
    int ready[2], go[2];
    char buf;
    int nevents;

    nevents = TOTAL_NUM_EVENTS;
    go[0]=go[1] = -1;

    for (grp = 0; grp < nevents; grp++) {
        int ret;
        ret = perf_setup_list_events(perf_events.pmc[grp], &fds_pid[app_num], &num_fds);
        if (ret || !nevents)
            exit(1);
    }
   }

the header file perf_util.h does contain perf_setup_list_events function but during compilation

matrix.o: In function `read_counts(int, int)':
matrix.c:(.text+0xf20): undefined reference to `perf_setup_list_events(char const*, perf_event_desc_t**, int*)'
collect2: error: ld returned 1 exit status

This is the error I get. What could be the possible places I would have done the error? Any help would be appreciated.

This is how I compile.

g++ -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -c matrix.c
g++ -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -o matrix matrix.o perf_util.o /libpfm-4.5.0/perf_examples/../lib/libpfm.a 

Note: libpfm compiles using cc and I use g++. Could that be the problem? if yes, how should I solve it?

Here is how I compile it now:

cc -std=c99 -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -c matrix.c 
cc -std=c99 -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -o matrix matrix.o perf_util.o libpfm-4.5.0/perf_examples/../lib/libpfm.a 


error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token 
const char * pmc[TOTAL_NUM_EVENTS] = {"blah", "blahbar"}

I've a const char * array and this is the error I get.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
user3808088
  • 87
  • 1
  • 1
  • 10
  • 1
    Your program does not appear to be C++. Why are you compiling it with the C++ compiler? Try compiling it with `gcc` instead. (Yes, that could be the problem. If using `gcc` fixes the problem, that is technically speaking a bug in the library, but you needn't care about that if you use the proper tool.) – zwol Jul 07 '14 at 02:12
  • Thanks Zack. Here is what I got when I use gcc and this is how I compile it. `cc -std=c99 -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -c matrix.c` `cc -std=c99 -I. -I/libpfm-4.5.0/perf_examples/../include -DCONFIG_PFMLIB_DEBUG -DCONFIG_PFMLIB_OS_LINUX -I. -D_GNU_SOURCE -pthread -w -o pmatrix pmatrix.o perf_util.o libpfm-4.5.0/perf_examples/../lib/libpfm.a ` `error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘__attribute__’ before ‘=’ token const char * pmc[TOTAL_NUM_EVENTS] = {` Any idea what I should do here? – user3808088 Jul 07 '14 at 02:14
  • 1
    @user3808088 post that in your question rather than in the comment, and indicate which line the error came from. There is no `const char * pmc` in the code you showed. – M.M Jul 07 '14 at 02:17
  • @user3808088 What Matt McNab said; also, we need to see the entire top-level construct containing the line that triggered that error. There isn't enough information in what you quoted to tell what the problem is. – zwol Jul 07 '14 at 02:18
  • @user3808088 Another thing to try, btw: continue compiling with `g++`, but put "`extern "C" {`" on a line by itself immediately before `#include "perf_util.h"`, and `}` on a line by itself immediately afterward. (There must not be anything inside that brace block except that one `#include`.) – zwol Jul 07 '14 at 02:20
  • @Zack: How do I do that. Could you please maybe post a solution. I will give it a shot. – user3808088 Jul 07 '14 at 02:21
  • `extern "C" { #include "perf_util.h" }` would do? – user3808088 Jul 07 '14 at 02:23
  • @user3808088 Exactly that, but with `extern "C" {`, `#include "perf_util.h"`, and `}` each on its own line. I will post an answer after you tell me whether that worked. – zwol Jul 07 '14 at 02:24
  • Your code example and the issues that you are trying to get answes to are too broad and there is little there to work with. As it stands there are number of referenced variables that are undefined there is no compilable code, your headers are missing you don't know how to link libraries ... too many issues in this question – Ahmed Masud Jul 07 '14 at 02:26
  • I still have the same problem. No change. EDIT: It did! – user3808088 Jul 07 '14 at 02:26
  • @AhmedMasud On the contrary: I know exactly what is wrong just from the information given already. – zwol Jul 07 '14 at 02:29
  • @n.m. Hmm, yes, specifically https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix/12574420#12574420 but I'm going to write out a less telegraphic answer here anyway, because that answer doesn't give any hint of how to tell that this is the problem. – zwol Jul 07 '14 at 02:31
  • Please be aware thar C and C++ are two very different languages. If you intend to learn one of them, make sure you have a book that mentions just thar one in the title (not both). – n. m. could be an AI Jul 07 '14 at 02:38
  • Thanks for that n.m. I still think `extern` wwill throw segfaults in other parts of the code. – user3808088 Jul 07 '14 at 02:42
  • @user3808088 If you get segfaults, please post a new question about that. But please read https://stackoverflow.com/help/mcve first. – zwol Jul 07 '14 at 02:48

1 Answers1

0

OK, so, contrary to what I thought at first, your program is a C++ program. We know this is the case because the C++ compiler accepts it and the C compiler doesn't. (You still haven't given enough information for me to understand why the C compiler doesn't like it, but I suspect it's something uninteresting like defining a file-scope variable that can't be fully initialized at compile time. If you meant this to be a C program you should ask a new question about that. Anyway.)

The library you are using is C, not C++, and its header files are not set up to be used from C++ programs. I deduced that this was the problem from the error message:

undefined reference to `perf_setup_list_events(char const*, perf_event_desc_t**, int*)'

See how that error message gives a full prototype for the function perf_setup_list_events? That's because C++ has function overloading and C doesn't -- so, in C++, every function is given a "mangled name" which encodes its prototype. If you do nm matrix.o | grep perf_setup_list_events you will discover this mangled name: it's probably something like _Z22perf_setup_list_eventsPKcPP17perf_event_desc_tPi. The linker is helpfully decoding that again to a prototype.

So, the fact that the linker error has a full prototype, all by itself, tells me that the undefined reference is from code compiled as C++. Now, I have never heard of libpfm4.5.0 before, but I do know that you would have gotten a different error message if your library didn't actually define that function -- something like

error: ‘perf_setup_list_events’ was not declared in this scope

So I guessed that the library is written in C, not C++, and that its header files are not written to handle being used from C++ programs. This is a defect in the library, but one that can be worked around by writing

extern "C" {
#include "perf_util.h"
}

instead of just the bare #include. The extern "C" { ... } construct tells a C++ compiler to not apply name mangling to whatever is declared within. Thus, your program, when compiled that way, looks for a symbol named perf_setup_list_events instead of _Z22perf_setup_list_eventsPKcPP17perf_event_desc_tPi and it links successfully.

zwol
  • 135,547
  • 38
  • 252
  • 361