GSL multiple error handler definition error when linking - c

I'm currently trying to use a library previously written by me (matrix.c) within another self-written library (Quaternion.c) by calling it through a header file using the standard method of using a "matrix.h" file with function prototypes from the "matrix.c" file.
"matrix.c" is functional, but when I attempt to compile "Quaternion.c" in MSYS2 MinGW64, using:
gcc -c matrix.c
gcc -c Quaternion.c
gcc matrix.o Quaternion.o -o Quaternion -lgsl
I'm getting this error:
C:/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: Quaternion.o:Quaternion.c:(.text+0x0): multiple definition of `my_handler'; matrix.o:matrix.c:(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status
I defined a custom error handler in the GSL "errono.h", and I'm assuming that's the source of the error:
void my_handler (const char * reason, const char * file, int line, int gsl_errno){
if(gsl_errno == 3 || gsl_errno == 7 || gsl_errno == 8 || gsl_errno == 10){
printf("Fatal memory-based error %d, resetting\n", gsl_errno);
exit(0);
//Reset Chip
}
if(gsl_errno == 1 || gsl_errno == 2 || gsl_errno == 4){
printf("User error %d (%s), ignoring calculation and moving forward\n", gsl_errno, reason);
// Return/ignore calculation
}
else
printf("Unexpected error %d, ignoring and moving forward\n", gsl_errno);
// Return/ignore calculation
}
I can't wrap my head around this error because the gsl library is a single source that I've already edited. If somebody could explain why my compilation method (I'm thinking that's what it is) is resulting in the re-definition of that handler, it would be appreciated.

Move the code quote into one of the .c files.
Then only provide the prototype in the .h file.
void my_handler (const char * reason, const char * file, int line, int gsl_errno);
Otherwise the function is defined once for each .c file which gets compiled and does a #include of that header. In your case probably twice.
A reinclusiong guard would not help in this case, because it still happens once per compiled .c file. But having a guard is still a good idea, I assume you have.

Related

Link errors using FANN

I'm trying to build a basic FANN (Fast Artificial Neural Network) project on Windows with MinGW. However, whenever I try to link the executable, I run into a bunch of undefined reference to errors. Interestingly, if I don't link the library at all, I get more errors, implying that at least some of the library is working. The code for the file I'm trying to compile and link is:
#include "doublefann.h"
int main() {
const unsigned int num_input_neurons = 9;
const unsigned int num_output_neurons = 1;
const unsigned int num_layers = 3;
const unsigned int num_hidden_neurons = 9;
const float desired_error = (const float) 0;
const unsigned int max_epochs = 500000;
const unsigned int epochs_between_reports = 1000;
struct fann *ann = fann_create_standard(num_layers,
num_input_neurons,
num_hidden_neurons,
num_output_neurons);
fann_set_activation_function_hidden(ann, FANN_SIGMOID_SYMMETRIC);
fann_set_activation_function_output(ann, FANN_SIGMOID_SYMMETRIC);
fann_train_on_file(ann,
"titanic-training.data",
max_epochs,
epochs_between_reports,
desired_error);
fann_save(ann, "titanic.net");
fann_destroy(ann);
return 0;
}
and the command I'm using to compile and link is:
gcc -Wall -Ifann\src\include titanic-train.c -Lfann\bin -lfanndouble -o titanic-train.exe
The errors I'm getting back are:
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0x7f): undefined reference to `fann_set_activation_function_hidden'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0x93): undefined reference to `fann_set_activation_function_output'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xbf): undefined reference to `fann_train_on_file'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xd3): undefined reference to `fann_save'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xdf): undefined reference to `fann_destroy'
c:/fragileprograms/mingw-native/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o: bad reloc address 0x64 in section `.rdata'
c:/fragileprograms/mingw-native/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
If I don't link the library at all, I instead get:
C:\Users\kunkelwe\AppData\Local\Temp\ccyOO3jL.o:titanic-train.c:(.text+0x67): undefined reference to `fann_create_standard'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0x7f): undefined reference to `fann_set_activation_function_hidden'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0x93): undefined reference to `fann_set_activation_function_output'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xbf): undefined reference to `fann_train_on_file'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xd3): undefined reference to `fann_save'
C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o:titanic-train.c:(.text+0xdf): undefined reference to `fann_destroy'
c:/fragileprograms/mingw-native/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\kunkelwe\AppData\Local\Temp\ccsWQg66.o: bad reloc address 0x64 in section `.rdata'
c:/fragileprograms/mingw-native/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation
collect2.exe: error: ld returned 1 exit status
Edit:
As per Haroogan's request, I ran nm fanndouble.lib. The output is rather extensive, so rather than paste it all here, I've made it available via pastebin here: http://pastebin.com/raw.php?i=vybFhEcX
I'm not familiar with nm, but it appears that the missing symbols do exist in the file.
Edit #2:
The contents of doublefann.h are: http://pastebin.com/mrHKJi8C
and the contents of fann.h, which it includes are: http://pastebin.com/gTrHCYAg
Could the problem just be solved by recompiling the library with MinGW?
Edit #3:
Making the changes that Haroogan suggested worked! In addition to those changes, I had to modify the CMakeLists.txt file for FANN by adding:
if (WIN32)
ADD_DEFINITIONS(-DFANN_DLL_EXPORTS)
endif (WIN32)
Then, running cmake -G "MinGW Makefiles" and then mingw32-make in the root of the project produced a file, libdoublefann.dll, that when linked against and included in the directory of the .exe, allowed me, finally, to run my program.
In doublefann.h on the line #116:
#if (_MSC_VER > 1300)
change to:
#if (_MSC_VER > 1300) || defined(__MINGW32__) || defined(__MINGW64__)
Furthermore, on the line #121:
#if defined(_MSC_VER) && (defined(FANN_USE_DLL) || defined(FANN_DLL_EXPORTS))
change to:
#if (defined(_MSC_VER) || defined(__MINGW32__) || defined(__MINGW64__)) && \
(defined(FANN_USE_DLL) || defined(FANN_DLL_EXPORTS))

Symbol not found in header file

I have this c program:
#include <sys/types.h>
#include "ourhdr.h"
int glob = 6; /* external variable in initialized data */
char buf[] = "a write to stdout\n";
int
main(void)
{
int var; /* automatic variable on the stack */
pid_t pid;
var = 88;
if (write(STDOUT_FILENO, buf, sizeof(buf)-1) != sizeof(buf)-1)
err_sys("write error");
printf("before fork\n"); /* we don't flush stdout */
if ( (pid = fork()) < 0)
err_sys("fork error");
else if (pid == 0) { /* child */
glob++; /* modify variables */
var++;
} else
sleep(2); /* parent */
printf("pid = %d, glob = %d, var = %d\n", getpid(), glob, var);
exit(0);
}
In the header file "ourhdr.h" (located in the same folder) i defined several functions, such as err_sys().
I get this error while compiling with gcc:
In function "main":
undefined reference to "err_sys"
How can i get this working? I can post the header file here if needed. Thank you.
** EDIT: ** This is the ourhdr.h file: http://pastebin.com/fMUiG4zU
You have included the header file with the declaration of err_sys. Ensure you have also an implementation that is passed to the linker. Background:
The compiler compiles a module to an object file:
g++ -c modul1.c generates modul1.o
g++ -c modul2.c generates modul2.o
Each of the modules can reference functions that are defined in a included header file. Up to here, no actual implementation of that function is needed.
In the next step, the linker links toghether all object files (and libraries):
g++ modul1.o modul2.o generates ./a.out or similar
In the second step, an implementation for all used functions is needed. Be sure you provided it!
(P.S.: Some compilers allow compiling and linking with one command, if you have multiple modules you can perhaps add them to a single gcc-call. I'd recomment to use make though)
I think what's likely to happen is that you have a header, ourhdr.h, containing the definition of the function, but the implementation is in a different file: ourhdr.c. In that case, if you try to compile without including ourhdr.c you'll get a reference error:
$ gcc main.c
/bin/ld: /tmp/ccVzNF6w.o: in function `main':
main.c:(.text+0x38): undefined reference to `err_sys'
To fix it, you need to compile like this:
$ gcc main.c ourhdr.c
Another option is to define the body of the function in ourhdr.h:
// ourhdr.h
#include <stdio.h>
void err_sys(const char* str);
void err_sys(const char* str) {
fprintf(stderr, "%s\n", str);
}
In that case, gcc main.c should work.
For me, it is compiling and working fine if you write the function name is written correctly.

Multiple definition and first defined in my C program

I am reading APUE (Stevens' "Advanced Programming in the UNIX Environment"), so there is a file "apue.h" which includes some self-definition function declared. I write a file named "wait.c" which defines functions WAIT_CHILD, WAIT_PARENT declared in "apue.h", and 14.6.c is the main function.
tmp/cciYhMd7.o: In function `err_ret':
14.6.c:(.text+0x0): multiple definition of `err_ret'
/tmp/ccO4WyJS.o:wait.c:(.text+0x0): first defined here
err_ret is just used not defined, so what's the problem??
wait.c
#include "apue.h"
static volatile sig_atomic_t sigflag;
static sigset_t newmask, oldmask, zeromask;
static void
sig_usr(int signo)
{
sigflag = 1;
}
void
TELL_WAIT(void)
{
if(signal(SIGUSR1, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR1) error");
if(signal(SIGUSR2, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR2) error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
sigaddset(&newmask, SIGUSR2);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
}
void
TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2);
}
void
WAIT_PARENT(void)
{
while(sigflag == 0)
sigsuspend(&zeromask);
sigflag = 0;
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}
void
TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR2);
}
void
WAIT_CHILD(void)
{
while(sigflag == 0)
sigsuspend(&zeromask);
sigflag = 0;
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}
The code above is my "wait.c" source file. I just use err_sys. Below is the linking command line and the linker error messages I'm getting:
$ gcc -o a.out wait.c 14.6.c
/tmp/ccZ5F3Pn.o: In function `err_ret':
14.6.c:(.text+0x0): multiple definition of `err_ret'
/tmp/cc5EXGbf.o:wait.c:(.text+0x0): first defined here
/tmp/ccZ5F3Pn.o: In function `err_sys':
14.6.c:(.text+0x38): multiple definition of `err_sys'
/tmp/cc5EXGbf.o:wait.c:(.text+0x38): first defined here
/tmp/ccZ5F3Pn.o: In function `err_exit':
14.6.c:(.text+0x76): multiple definition of `err_exit'
/tmp/cc5EXGbf.o:wait.c:(.text+0x76): first defined here
/tmp/ccZ5F3Pn.o: In function `err_dump':
14.6.c:(.text+0xaf): multiple definition of `err_dump'
/tmp/cc5EXGbf.o:wait.c:(.text+0xaf): first defined here
/tmp/ccZ5F3Pn.o: In function `err_msg':
14.6.c:(.text+0xe6): multiple definition of `err_msg'
/tmp/cc5EXGbf.o:wait.c:(.text+0xe6): first defined here
/tmp/ccZ5F3Pn.o: In function `err_quit':
14.6.c:(.text+0x116): multiple definition of `err_quit'
/tmp/cc5EXGbf.o:wait.c:(.text+0x116): first defined here
/tmp/ccZ5F3Pn.o: In function `TELL_WAIT':
14.6.c:(.text+0x5fe): multiple definition of `TELL_WAIT'
/tmp/cc5EXGbf.o:wait.c:(.text+0x272): first defined here
/tmp/ccZ5F3Pn.o: In function `TELL_CHILD':
14.6.c:(.text+0x72e): multiple definition of `TELL_CHILD'
/tmp/cc5EXGbf.o:wait.c:(.text+0x3a2): first defined here
/tmp/ccZ5F3Pn.o: In function `WAIT_PARENT':
14.6.c:(.text+0x6d8): multiple definition of `WAIT_PARENT'
/tmp/cc5EXGbf.o:wait.c:(.text+0x34c): first defined here
/tmp/ccZ5F3Pn.o: In function `TELL_PARENT':
14.6.c:(.text+0x6bd): multiple definition of `TELL_PARENT'
/tmp/cc5EXGbf.o:wait.c:(.text+0x331): first defined here
/tmp/ccZ5F3Pn.o: In function `WAIT_CHILD':
14.6.c:(.text+0x749): multiple definition of `WAIT_CHILD'
/tmp/cc5EXGbf.o:wait.c:(.text+0x3bd): first defined here
collect2: ld returned 1 exit status
do not define functions or variables in header files. declare them in header files, define them in .c source files.
you need to create a separate source file for the definitions and compile it separately.
also, be aware of the difference between declaration of global variables and deifnition. If you need to declare a variable that is used by multiple .c files, you must say:
extern int err__ret;
to declare the variable (as an external variable) in your header file, then add:
int err_ret;
to one .c file, to define it.
Note also, any .c file that defines a variable or function should also include the .h file that declares it. This will cause the compiler to produce an error if there are any discrepancies between the declaration and the definition.
The source from the APUE book's web site has these three declarations (amongst many others) in apue.h:
void err_ret(const char *, ...);
void WAIT_PARENT(void);
void WAIT_CHILD(void);
Judging from the error message from your compiler, not only is err_ret() defined, it is in fact defined twice, once in your source file wait.c and once in your source file 14.6.c. You will need to decide which (if either) of those definitions is correct, and remove the other, or decide that you can't use the code in wait.c with your program in 14.6.c. It might be better still to put err_ret() and friends into their own source file. In the source, the err_*() functions are in lib/error.c.
I didn't redefine the functions err_*(), so I think I use the lib/error.c source file. And in apue.h there's:
#ifndef _APUE_H
#define _APUE_H
so I think it won't defined twice.
If your TU (translation unit) does #include "lib/error.c", then your TU is defining the functions. The C compiler sees the source code containing your source plus the headers you include plus (hypothetically) the code in lib/error.c. You simply shouldn't be including that source file; you should compile it separately and link the object file into your program. The apue.h header declares the err_*() functions so you can use them in your code. You are expected to compile lib/error.c separately and link it with your wait.o and 14.6.o files.
It is crucial to understand the difference between defining a variable or function (actually allocating the storage for it) and declaring a variable or function (telling the compiler that the function or variable exists, but that it is not defined here — as in 'this declaration does not define it', even if the next line in the source file does define it). Headers should provide declarations and should not provide definitions (most of the time — it's a good enough rule for now, until you know enough to know when and how to break the rule).
But what I do is just #include "apue.h" when I write my source file. I don't quite understand how to separately compile lib/error.c.
So, it sounds like you need three source files in your compile and link line:
gcc -o 14.6 14.6.c wait.c lib/error.c
Or you might do it in separate operations:
gcc -c 14.6.c
gcc -c wait.c
gcc -c lib/error.c -o error.o
gcc -o 14.6 14.6.o wait.o error.o
You might need extra compiler flags (-I or -D options for example), or extra libraries and linker options (-llib and -L /directory/lib options, for example).
If your source files 14.6.c and wait.c contain #include "apue.h" and do not include other source files (so no #include "lib/error.c" or anything similar — and 14.6.c does not include your wait.c nor vice versa), then you should not run into problems.
However, you are running into problems, and we can't see your source or your linking command, which means we have to try and guess what you've done wrong. We can devise all sorts of outlandish examples of what you might be doing, but we're most likely to be wrong.
So, keeping the code to a minimum, show us which files you are compiling and how you are compiling them.
please show wait.h's entry of err_ret(), you can obscure other lines if you want. No one is asking you to compromise your NDA :)(pun intended). also have you declared err_ret() again in wait.c? if you have then it won't compile.(i'm guessing that's where the problem lies)
do preprocessing first to find multiple definitions like below:
$gcc -E wait.c | grep -n 'err_ret'
$gcc -E 14.6.c | grep -n 'err_ret'
look through the output and line numbers to find out where exactly the functions are declared and defined.
I met the similar problem when I compiling my sigsetjmp.c. Finally I find the reason is that I had #include "error.c" in my apue.h, which result in when compiling multiple c files, each file include apue.h, and then include error.c, lead to the multiple definition of the err_ret error.
Here's my suggestion:
Don't include any function definition c file in head file (the apue.h).
Required other c file in gcc command line or Makefile is OK.
eg: gcc sigsetjmp.c pr_mask.c error.c
Hope this help.

undefined reference to function declared in *.h file

I am a unskilled programmer and new to linux, I run into a problem when complining. I have two files 'ex_addinst.c' and 'lindo.h' in the same folder, I input command :
g++ -c ex_addinst.c
then, a object file ex_addinst.o is genetated with a warning:
ex_addinst.c: In function ‘int main()’:
ex_addinst.c:80: warning: deprecated conversion from string constant to ‘char*’
then I leak them with
g++ -Wall -o ex_addinst ex_addinst.o
and get the following info:
ex_addinst.o: In function `main':
ex_addinst.c:(.text+0x2b): undefined reference to `LSloadLicenseString'
ex_addinst.c:(.text+0x75): undefined reference to `LSgetVersionInfo'
ex_addinst.c:(.text+0xae): undefined reference to `LScreateEnv'
ex_addinst.c:(.text+0x10a): undefined reference to `LSgetErrorMessage'
...
...
ex_addinst.c:(.text+0x1163): undefined reference to `LSdeleteEnv'
collect2: ld returned 1 exit status
I guess that the header file 'lindo.h' is not complied into the .o file, but I have no idea what to do now. I have tried gcc, but get the same error. the version of my g++ and gcc is 4.4.5. I am using Ubuntu 10.10.
All the functions and structures have been declared in 'lindo.h'.
part of ex_addinst.c is as follows:
#include <stdio.h>
#include <stdlib.h>
/* LINDO API header file */
#include "lindo.h"
enter code here
int CALLTYPE LSwriteMPIFile(pLSmodel pModel,
char *pszFname);
/* Define a macro to declare variables for
error checking */
#define APIERRORSETUP \
int nErrorCode; \
char cErrorMessage[LS_MAX_ERROR_MESSAGE_LENGTH] \
/* Define a macro to do our error checking */
#define APIERRORCHECK \
if (nErrorCode) \
{ \
if ( pEnv) \
{ \
LSgetErrorMessage( pEnv, nErrorCode, \
cErrorMessage); \
printf("nErrorCode=%d: %s\n", nErrorCode, \
cErrorMessage); \
} else {\
printf( "Fatal Error\n"); \
} \
exit(1); \
} \
#define APIVERSION \
{\
char szVersion[255], szBuild[255];\
LSgetVersionInfo(szVersion,szBuild);\
printf("\nLINDO API Version %s built on %s\n",szVersion,szBuild);\
}\
/* main entry point */
int main()
{
APIERRORSETUP;
pLSenv pEnv;
pLSmodel pModel;
char MY_LICENSE_KEY[1024];
/*****************************************************************
* Step 1: Create a model in the environment.
*****************************************************************/
nErrorCode = LSloadLicenseString("home/li/work/tools/lindo/lindoapi/license/lndapi60.lic", MY_LICENSE_KEY);
if ( nErrorCode != LSERR_NO_ERROR)
{
printf( "Failed to load license key (error %d)\n",nErrorCode);
exit( 1);
}
......
......
......
APIERRORCHECK;
{
int nStatus;
double objval=0.0, primal[100];
/* Get the optimization result */
nErrorCode = LSgetInfo(pModel, LS_DINFO_GOP_OBJ, &objval);
APIERRORCHECK;
LSgetMIPPrimalSolution( pModel, primal) ;
APIERRORCHECK;
printf("\n\nObjective = %f \n",objval);
printf("x[0] = %f \n",primal[0]);
printf("x[1] = %f \n",primal[1]);
/* Get the linearity of the solved model */
nErrorCode = LSgetInfo (pModel, LS_IINFO_GOP_STATUS, &nStatus);
APIERRORCHECK;
/* Report the status of solution */
if (nStatus==LS_STATUS_OPTIMAL || nStatus==LS_STATUS_BASIC_OPTIMAL)
printf("\nSolution Status: Globally Optimal\n");
else if (nStatus==LS_STATUS_LOCAL_OPTIMAL)
printf("\nSolution Status: Locally Optimal\n\n");
else if (nStatus==LS_STATUS_INFEASIBLE)
printf("\nSolution Status: Infeasible\n\n");
}
/* >>> Step 7 <<< Delete the LINDO environment */
LSdeleteEnv(&pEnv);
/* Wait until user presses the Enter key */
printf("Press <Enter> ...");
getchar();
}
part of 'lindo.h' is:
/*********************************************************************
* Structure Creation and Deletion Routines (4) *
*********************************************************************/
pLSenv CALLTYPE LScreateEnv(int *pnErrorcode,
char *pszPassword);
pLSmodel CALLTYPE LScreateModel(pLSenv pEnv,
int *pnErrorcode);
int CALLTYPE LSdeleteEnv(pLSenv *pEnv);
int CALLTYPE LSdeleteModel(pLSmodel *pModel);
int CALLTYPE LSloadLicenseString(char *pszFname, char *pachLicense);
void CALLTYPE LSgetVersionInfo(char *pachVernum, char *pachBuildDate);
Thank you!
Thank you guys answering my problem. As you suggested, I need to link the library when complining. I have gotten the executable file with:
gcc -o ex_addinst ./ex_addinst.o -L/home/li/work/tools/lindo/lindoapi/bin/linux64 -m64 -llindo64 -lmosek64 -lconsub3 -lc -ldl -lm -lguide -lpthread -lsvml -limf -lirc
but there comes another problem when run the executable file ex_addinst: after run:
./ex_addinst
there comes:
./ex_addinst: error while loading shared libraries: liblindo64.so.6.0: cannot open shared object file: No such file or directory
The tricky thing is, liblindo64.so.6.0 is in the lib folder which contains:
libconsub3.so libirc.so liblindojni.so libmosek64.so.5.0 lindo.par
libguide.so liblindo64.so liblindojni.so.6.0.3 libsvml.so placeholder
libimf.so liblindo64.so.6.0 libmosek64.so lindoapivars.sh runlindo
I have created symbolic links between liblindo64.so.6.0 and liblindo64.so with
ln -sf liblindo64.so.6.0 liblindo64.so
but it doesn't help.
Can anyone tell me what is wrong here?
(I am not sure I should put this question in a new post, but I think currently it is better to follow the old one)
Ok, lindo.h contains the prototypes for those functions, but where are the functions actually defined? If they're in another C file you need to compile that one too, and link both the object files together.
If the functions are part of another static library, you need to tell the linker to link that library along with your object file.
If they're defined with a shared library, you can probably get g++ to still link to it at compile time, and take care of the library loading etc. Otherwise you'll need to load the library at runtime and reference the functions from the library. This Wikipedia article on dynamic loading of shared libraries contains some example code.
Try
g++ -Wall -o ex_addinst ex_addinst.c
instead of
g++ -Wall -o ex_addinst ex_addinst.o
You want to compile the .c file, not the .o file.
You need to tell gcc to link with the library or object file(s) that contain the LS... functions you're using. The header file tells the compiler how to call them, but the linker needs to know where to get the compiled code from.
undefined reference to ... is not a declaration problem. The compiler fails because it can't find symbols (objects) which are related to those declared functions.
In your case, you use the Limbo API, and include the header file, but you don't tell the compiler to link with the library : that's why it doesn't find symbols.
EDIT : I had forgotten the part when you say you're new to Linux. To link with the library, you need to use the -L/-l options of g++. man g++ is always a good read, and the Limbo's documentation should be, too.

Compiling a C program

i am trying to compile this code, but if i do using:
gcc prt.c portaudio.h -o prt
but i get this error:
main.c:47: undefined reference to `Pa_OpenDefaultStream'
main.c:62: undefined reference to `Pa_StartStream'
main.c:65: undefined reference to `Pa_Sleep'
main.c:66: undefined reference to `Pa_StopStream'
main.c:69: undefined reference to `Pa_CloseStream'
main.c:72: undefined reference to `Pa_Terminate'
main.c:78: undefined reference to `Pa_Terminate'
i don't know why, then i though it might be beacuse i don't have a rule (make file)
so i made one:
main: main.o
gcc main.o -o main
main.o: main.c portaudio.h
gcc -c main.c
but when i try to run it through cygwin: using "Make"
i get this message:
"make: *** No targets specified and no makefile found. Stop.
I don't understand the problem, please help me is something wrong with my makefile or is there something else wrong.
also this is the code:
main.c
#include <stdio.h>
#include "portaudio.h"
#define SAMPLE_RATE (44100)
typedef struct
{
float left_phase;
float right_phase;
}
paTestData;
static int patestCallback( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData )
{
/* Cast data passed through stream to our structure. */
paTestData *data = (paTestData*)userData;
float *out = (float*)outputBuffer;
unsigned int i;
(void) inputBuffer; /* Prevent unused variable warning. */
for( i=0; i<framesPerBuffer; i++ )
{
*out++ = data->left_phase; /* left */
*out++ = data->right_phase; /* right */
/* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
data->left_phase += 0.01f;
/* When signal reaches top, drop back down. */
if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;
/* higher pitch so we can distinguish left and right. */
data->right_phase += 0.03f;
if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;
}
return 0;
}
static paTestData data;
int main (void) {
PaStream *stream;
PaError err;
err = Pa_OpenDefaultStream( &stream,
0, /* no input channels */
2, /* stereo output */
paFloat32, /* 32 bit floating point output */
SAMPLE_RATE,
256, /* frames per buffer, i.e. the number
of sample frames that PortAudio will
request from the callback. Many apps
may want to use
paFramesPerBufferUnspecified, which
tells PortAudio to pick the best,
possibly changing, buffer size.*/
patestCallback, /* this is your callback function */
&data ); /*This is a pointer that will be passed to
your callback*/
err = Pa_StartStream( stream );
if( err != paNoError ) goto error;
Pa_Sleep(9*1000);
err = Pa_StopStream( stream );
if( err != paNoError ) goto error;
err = Pa_CloseStream( stream );
if( err != paNoError ) goto error;
err = Pa_Terminate( );
if( err != paNoError ) goto error;
printf("Test finished.\n");
return err;
error:
Pa_Terminate();
return err;
}
and the header file portaudio.h: Portaudio.h
if you want cleaner view of main.c: main.c
I am not so sure why these messages/errors/warning are coming, please help.
also this is my folder view:
You seem to be using functions from a library for the 'Port Audio' facility, but your link line does not tell the C compiler how to find that library - so the functions show up as undefined references.
Your link line should look something like:
gcc -o main main.o -lpa
That should be macroized, but the gist is correct.
This assumes the library is in 'libpa.a' or thereabouts. If it is in 'libportaudio.so', then use -lportaudio instead of -lpa.
Using macros in the makefile:
PROGRAM = main
SOURCE = main.c
OBJECT = $(SOURCE:.c=.o)
LIBDIR = /cygdrive/c/installdir/portaudio/lib
LIBRARY = $(LIBDIR)/portaudio_x86.lib
$(PROGRAM): $(OBJECT)
$(CC) $(CFLAGS) -o $# $(OBJECT) $(LDFLAGS) $(LIBRARY)
main.o: main.c portaudio.h
You should not need an explicit compilation command for main.o; make should be able to deduce that from its internal rules. Note that the character before $(CC) must be a TAB and not spaces.
The make command only looks for a file called makefile or Makefile, to use make with a differently named makefile, you need to do make -f otherfile target.
Rename your file Make file to Makefile to have make look at its contents. Also, verify that you use one tab character (no spaces) in all of the commands under a target. You might have done that, but your cut-and-paste of the contents in this posting doesn't let us know if that is really how it is.
It would also appear that you need the PortAudio library to link to or those functions will not be defined. That is, unless they're defined in the header (I haven't used that library before...)
Did portaudio come with a .lib or anything? The header file only contains the name of the functions, not the definitions. You'll need to link against the library to get the functionality for all of those functions
Your initial problem ("Undefined reference to...") is a message from the linker saying it cannot find a definition of the functions mentioned. This means you need to add a linker argument saying that you want to add the library providing these functions (lib portaudio?) to your program. GCC's command line parameter to do so is "-l"
It seems like you need to include the library (with a -l[library name] option.
A search of portaudio compile commands shows libportaudio.a included in the gcc options.
You are probably not linking to those libraries libs (.so or .a) look at the documentation and see what libs you need to link your program with.
The other thing is that when you run "make -f Makefile" you need to have a tab in your makefile before the "gcc..." lines i.e. the command lines.
I also need to add -lm, otherwise it throws an error.
So gcc -o test test.c -lm -lportaudio

Resources