I'm trying to write a c function(that later will be used in R scripts) that uses BLAS lib from R
#include <stdio.h>
#include <R.h>
#include <R_ext/BLAS.h>
void foo(int *dimension, double *vect1, double *vect2)
{
const int dim = dimension[0];
const int incxy = 1;
//swaps two vectors
F77_NAME(dswap)(&dim,vect1,&incxy,vect2,&incxy);
}
I compile the code using :
R CMD SHLIB foo.c
I get the error :
foo.o:foo.c:(.text+0x41): undefined reference to `dswap_'
What am i missing ?
Including a header file is not the same as linking a library.
I don't actually know anything about R, but I did some searching and found http://cran.r-project.org/doc/manuals/R-exts.html#Creating-shared-objects which indicates you need the BLAS_LIBS variable - if you're not using a makefile it looks like you can just get the output of the command "R CMD config BLAS_LIBS" and then include the output on the command line. You might also be able to just add it to the PKG_LIBS variable, but I don't know enough about R to be sure.
EDIT:
have set file Makevars.win to include
PKG_LIBS=$(BLAS_LIBS)
PKG_LIBS=$(LAPAK_LIBS)
That replaces the PKG_LIBS variable with LAPAK_LIBS. Try it with += instead of =.
have set file
Makevars.win to include
PKG_LIBS=$(BLAS_LIBS)
PKG_LIBS=$(LAPAK_LIBS)
but error persists.
BINGO : added to
"R CMD SHLIB foo.c"
the output from
"R CMD config BLAS_LIBS"
as in
"R CMD SHLIB foo.c -LC:/PROGRA~1/R/R-212~1.2/bin/i386 -lRblas"
and now it works.
It needs to be linked to whatever provides the dswap function. I would guess that's in the R library.
It works here (and please ignore that my ~/.R/Makevars selects a particular CC and CFLAGS; and also ignore minor whitespace edits):
edd#max:/tmp$ R CMD SHLIB foo.c
gcc-4.5 -I/usr/share/R/include -fpic -O3 -g0 -Wall -pipe -pedantic -std=gnu99 \
-c foo.c -o foo.o
gcc -shared -o foo.so foo.o -L/usr/lib64/R/lib -lR
edd#max:/tmp$ cat foo.c
#include <stdio.h>
#include <R.h>
#include <R_ext/BLAS.h>
void foo(int *dimension, double *vect1, double *vect2)
{
const int dim = dimension[0];
const int incxy = 1;
//swaps two vectors
F77_NAME(dswap)(&dim,vect1,&incxy,vect2,&incxy);
}
edd#max:/tmp$
Ubuntu 10.10, stock packages for R, gcc etc. Maybe your R is locally built in a static library configuration?
Related
I have a project I'm working on that currently has a matrix.c file containing a some functions and has a corresponding header matrix.h. I made a shared library libccalc.so using matrix.c and another file. I am trying to create a directory in /usr/local/lib and a directory in /usr/local/include, both called ccalc to house the respective .so and .h files which can then later be used to compile programs using the functionality of libccalc.so. However, when I do this I am getting an error.
To be precise, matrix.c contains functions:
Matrix *mat_create(int rows, int cols),
void mat_fill(Matrix *mat, double *entries) and
void mat_print(Matrix *mat)
which are declared in matrix.h. I place the files in their respective directories as explained above, I run ldconfig /usr/local/lib/ccalc and I make a new file test.c in some other directory with the following:
// test.c
#include <stdio.h>
#include "matrix.h"
int main() {
Matrix *m = mat_create(2, 2);
double entries[4] = {1, 2, 3 ,4};
mat_fill(m, entries);
mat_print(m);
return 0;
}
matrix.h contains the following:
// matrix.h
#ifndef MATRIX_H
#define MATRIX_H
#define MAX_SIZE 50
typedef struct Matrix Matrix;
struct Matrix {
int rows;
int cols;
double *data;
};
Matrix *mat_create(int n, int p);
void mat_fill(Matrix *mat, double *entries);
void mat_print(Matrix *mat);
#endif
When I enter the command: gcc -I/usr/local/include/ccalc -L/usr/local/lib/ccalc -lccalc test.c -o test, I get the error:
/usr/bin/ld: /tmp/ccesD44J.o: in function `main':
test.c:(.text+0x26): undefined reference to `mat_create'
/usr/bin/ld: test.c:(.text+0x71): undefined reference to `mat_fill'
/usr/bin/ld: test.c:(.text+0x7d): undefined reference to `mat_print'
collect2: error: ld returned 1 exit status
However, when I place libccalc.so and matrix.h in /usr/local/lib and /usr/local/include, enter ldconfig and enter the command gcc -L/usr/local/lib/ccalc -lccalc test.c -o test, and run ./test, it works perfectly
Can someone tell me what I am doing wrong?
The order of program arguments to gcc matters a lot. Please read the documentation about Invoking GCC.
Also, test is often a builtin command. See test(1).
So (on Linux) rename test.c as prog.c then compile your program with
gcc -Wall -Wextra -g prog.c -L/usr/local/lib/ccalc -lccalc -o prog
Then use strace(1) and gdb(1) to understand the behavior of prog, and ldd(1), objdump(1) with readelf(1) to analyze prog. See also elf(5) and ld.so(8).
Regarding building shared libraries, read Drepper's paper How to write shared libraries
You probably want to compile matrix.c into libcalc.so using
gcc -fPIC -Wall -O -shared -g matrix.c -o libcalc.so
but you might need other program arguments.
Regarding matrix operations, this answer could be inspirational.
I have source files written in C programming using notepad++ and I am running them from command lines and later i need to link them inorder to generate the .exe file.
Here are the following commands I want to use while generating .exe file
gcc logc.c -o logc
gcc mainc.c -o mainc
gcc -o output logc.o mainc.o
But when i run the following command my compiler is returning with the following error status.
gcc logc.c -o logc
(x86)/mingw-w64/i686-8.1.0-win32-dwarf-rt_v6-rev0/mingw32/bin/../lib/gcc/i686-w64-mingw32/8.1.0/../../../../i686-w64-mingw32/lib/../lib/libmingw32.a(lib32_libmingw32_a-crt0_c.o):crt0_c.c:(.text.startup+0x39): undefined reference to `WinMain#16'
when i run the following command to compile my mainc file
C:\Users\user\AppData\Local\Temp\ccskY3nf.o:mainc.c:(.text+0x31): undefined reference to `Log'
collect2.exe: error: ld returned 1 exit status
And here are my mainc.c and logc.c and logc.h files for your reference
logc.c file is here
#include <stdio.h>
#include "logc.h"
void InitLog()
{
Log("Initializing Log");
}
void Log(const char* message)
{
printf(" %s",message);
}
mainc.c file is here
#include <stdio.h>
#include <conio.h>
#include <stdbool.h>
#include "logc.h"
int main()
{
int x = 5;
bool comparisonResult = x == 5;
if(comparisonResult == 1)
Log("Hello World");
return 0;
}
and logc.h file is here
#ifndef _LOG_H
#define _LOG_H
void InitLog();
void Log(const char* message);
#endif
How can i compile individual source files and then link them and generate an executable file.
Thanks in advance.
You don't create object files, for that you need the -c argument:
gcc logc.c -c
gcc mainc.c -c
gcc -o output logc.o mainc.o
By default gcc will generate an executable file, not an object file. So when you compile logc.c, it tries to make an executable but it can't find the main function so it fails. Similarly with main.c, it tries to make an executable but can't find Log
You need to add the -c option to create object files:
gcc logc.c -c -o logc.o
gcc mainc.c -c -o mainc.o
The code for the library:
calc_mean.c
//#include <stdio.h>
double mean(double a, double b) {
return (a+b) / 2;
}
The header file:
calc_mean.h
double mean(double, double);
The programm using the library:
main.c
#include <stdio.h>
#include "calc_mean.h"
int main(int argc, char* argv[]) {
double v1, v2, m;
v1 = 5.2;
v2 = 7.9;
m = mean(v1, v2);
printf("The mean of %3.2f and %3.2f is %3.2f\n", v1, v2, m);
return 0;
}
I created static library using following commands:
gcc -c calc_mean.c -o calc_mean.o
ar rcs libmean.a calc_mean.o
Linking against static library:
gcc -static main.c -L. -lmean -o statically_linked
everything works perfectly fine as long as its static library...
Now these are the commands which I used to create shared library:
gcc -c -fPIC calc_mean.c -o calc_mean.o
gcc -shared -Wl,-soname,libmean.so.1 -o libmean.so.1.0.1 calc_mean.o
after these two commands when I enter the linkng command
gcc main.c -o dynamically_linked -L. -lmean
I am getting error message can not find -lmean
ld returned 1 exit status
attaching error message here
can some one give me steps to create DLL in C?
This is because you are creating a file named libmean.so.1.0.1, but you ask the linker to link with libmean.so (this is what -lmean expands to).
You need a symbolic link libmean.so pointing to libmean.so.1.0.1.
When you try to link the lib by giving -lmean, it automatically searches for libmean.so, but you have created the lib as libmean.so.1.0.1. This is the problem. Either change the lib name or create a symbolic link.
Did you copy the libmean.so.1 in /usr/lib/ (or) /opt/lib/?
I want to access the global variable of executable in shared library? I have tried to compile using option -export-dynamic but no luck.
I have tried with extern key word. this also not working.
Any help or suggestion would be appreciable.
Environment c - Linux
executable:-
tst.c
int tstVar = 5;
void main(){
funInso();
printf("tstVar %d", tstVar);
}
lib:-
tstLib.c
extern int tstVar;
void funInso(){
tstVar = 50;
}
Since my code is very big, I just gave the sample which I have used in my program.
It should work. BTW, your tst.cis lacking a #include <stdio.h>. And its main should return an ìnt and end with e.g. return 0;.
With
/* file tst.c */
#include <stdio.h>
int tstVar = 5;
extern void funInso(void);
int main(){
funInso();
printf("tstVar %d\n", tstVar);
return 0;
}
and
/* file tstlib.c */
extern int tstVar;
void funInso(){
tstVar = 50;
}
I compiled with gcc -Wall -c tst.c the first file, I compiled with gcc -Wall -c tstlib.c the second file. I made it a library with
ar r libtst.a tstlib.o
ranlib libtst.a
Then I linked the first file to the library with gcc -Wall tst.o -L. -ltst -o tst
The common practice is to have with your library a header file tstlib.h which would contain e.g.
#ifndef TSTLIB_H_
#define TSTLIB_H_
/* a useful explanation about tstVar. */
extern int tstVar;
/* the role of funInso. */
extern void funInso(void);
#endif /*TSTLIB_H */
and have both tst.c and tstlib.c contain an #include "tstlib.h"
If the library is shared, you should
compile the library file in position independent code mode
gcc -Wall -fpic -c tstlib.c -o tstlib.pic.o
link the library with -shared
gcc -shared tstlib.pic.o -o libtst.so
Note that you can link a shared object with other libraries. You could have appended -lgdbm to that command, if your tstlib.c is e.g. calling gdbm_open hence including <gdbm.h>. This is one of the many features shared libraries give you that static libraries don't.
link the executable with -rdynamic
gcc -rdynamic tst.o -L. -ltst -o tst
Please take time to read the Program Library Howto
your tstVar variable could be defined in the lib. and you can share this variable via functions:
setFunction: to edit this variable
void setFunction (int v)
{
tstVar = v;
}
getFunction: to return the variable
int getFunction ()
{
return tstVar
}
In libname.h:
int add_libname(int, int);
In libname.c:
#include "libname.h"
int add_libname(int a, int b)
{
return a+b;
}
I can build the shared library this way:
gcc -shared -fPIC libname.c -o libname.so
But I can't use it in another programe test.c:
#include <stdio.h>
#include "libname.h"
int main(int argc, char* argv[])
{
printf("%d\n", add_libname(1,5));
}
Reporting undefined reference to add_libname when I try to build it..
What's wrong here?
Because add_libname takes (int, int) you're giving it (1+5 = 6) or just (int)
I think you meant
add_libname(1, 5);
Also to compile it correctly you must use gcc like so
gcc -o myapp test.c -L. -lname
the lib part of libname is ignored as it is implicit
To create a shared library use these
gcc -fPIC -c libname.c
it gives warning: position independent code and libname.o file is generated.
and now type these command,
gcc -shared libname.so libname.o
libname.so ( the shared library is created with .so extension). To use the shared library
gcc -I/give the path of libname.h sourcefile.c /give the path of your .so file
example if your c file is file.c and the header file libname.h is in c:\folder1\project and your libname.so (shared library) is in c:\folder\project2
then
gcc -I/cygdrive/c/folder1/project file.c /cygdrive/c/folder/project/libname.so
this is the gcc command to be used while using the shared library.
Thank you.