I have been able to write simple R extensions in C by doing the following:
writing a C function
compiling it using R CMD SHLIB "function name.c"
using dyn.load("functionname.so") in R
Now, I have written some more advanced C functions that use the igraph library. However, the compiling command above (R CMD SHLIB) does not recognize #include<igraph.h>. Is there a way to adapt the R CMD SHLIB command so that it will find the igraph library? When I compile my C code regularly, I use the following compile command to include igraph:
gcc -I MY_IGRAPH_DIR/install/include/igraph -L MY_IGRAPH_DIR/install/lib myfunction.c -o myfunction
I realize that to pass more than just an integer vector to C I will want to explore sexp and .Call. Currently, I am just trying to get small functions to work so that I have a place to start. Also, I prefer C and am trying to avoid RCPP.
Related
Using GtkAda, I'm trying to use the resource API to include the Glade file directly inside my code.
For this, we can generate C code from a set of resources using glib-compile-resources which can then be linked to the Ada code.
The problem is that this C code requires Gtk includes which we usually get from the pkg-config command under Linux such as
gcc -c -x c `pkg-config --cflags gio-2.0` myglade.gresource.c
I'd like to know how to provide the same kind of information in a GPRBuild project file.
FYI, I already tried to use the pkg-config command inside the compiler package for C language without any success. Of course, I managed to build by hand but that's a bit long :)
This might work for you:
project Config_Demo is
Pkg_Config := external_as_list ("PKG_CONFIG", " ");
package Compiler is
-- only this file needs the extra switches
for Switches ("myglade.gresource.c") use Pkg_Config;
end Compiler;
end Config_Demo;
and then
gprbuild -P config_demo -XPKG_CONFIG="`pkg-config -cflags gio-2.0`"
Your best bet will be to do what GtkAda does: Look at its shared.gpr.in file, it uses the token #GTK_LIBS_GPR# which will be replaced by the configure script, giving a usable shared.gpr.
Thing is, you need to issue the pkg-config call and build your gpr file from the result somehow. GPRBuild is not equipped to do this for you and process the result. If you're comfortable with GNU autotools, you can look further at how GtkAda achieves it:
GTK_LIBS_GPR is set in aclocal.m4 using a macro that converts the C-style flags to a GPR array. The value comes from GTK_LIBS which is queried here via pkg-config.
If you're not comfortable with GNU autotools, you can write your configure script using basic shell commandos, a scripting language like Python or with whatever other tool you're comfortable with.
I am working on an expression evaluator with 7 different C files, of which Test.c contains the main function. Others perform functions like infix to postfix, check precendence and the like. I have separately compiled each .c file to generate the object files(.o). How do I link and execute them ? (I am using gcc, Dev Cpp IDE and windows 10) I used cmd to compile (gcc -c filename.c) but am unable to link and execute the files.
I am constructing an R package where I have few third party C functions which use GSL and OpenMP, and I then call these from R using wrappers made with Rcpp (which just modify some arguments and call the appropriate C function). Everything works fine in my Windows machine, but I am not sure how to define the Makevars.win and Makevars file in a portable way. My Makevars.win looks like this:
## This assumes that the LIB_GSL variable points to working GSL libraries
PKG_CPPFLAGS=-I$(LIB_GSL)/include -I../inst/include
PKG_LIBS=-L$(LIB_GSL)/lib/x64 -lgsl -lgslcblas $(SHLIB_OPENMP_CFLAGS)
PKG_CFLAGS=$(SHLIB_OPENMP_CFLAGS)
It is basically copied from various sources. Like said, this compiles in my computer (using toolchain of from Rtools), and if I remove PKG_CFLAGS=$(SHLIB_OPENMP_CFLAGS) I can also compile without OpenMP (for some reason I don't understand I get error if I remove OpenMP flag in PKG_LIBS).
My Makevars file looks identical, but I don't have access to Unix platforms so I am not sure how to deal with that side. My guess is that I need to replace LIB_GSL with something?
EDIT:
Okay, I think I finally understand how configure etc. works and was able to get everything working.
My Makevars.win:
## This assumes that the LIB_GSL variable points to working GSL libraries
PKG_CPPFLAGS=-I$(LIB_GSL)/include -I../inst/include
PKG_LIBS="-L$(LIB_GSL)/lib/$(R_ARCH)" -lgsl -lgslcblas $(SHLIB_OPENMP_CFLAGS)
PKG_CFLAGS=$(SHLIB_OPENMP_CFLAGS)
My Makevars.in:
GSL_CFLAGS = #GSL_CFLAGS#
GSL_LIBS = #GSL_LIBS#
PKG_LIBS=$(GSL_LIBS) $(SHLIB_OPENMP_CFLAGS)
PKG_CFLAGS=$(GSL_CFLAGS) $(SHLIB_OPENMP_CFLAGS)
And my configure.ac:
AC_INIT([testpackage], 0.0.1)
## Use gsl-config to find arguments for compiler and linker flags
##
## Check for non-standard programs: gsl-config(1)
AC_PATH_PROG([GSL_CONFIG], [gsl-config])
## If gsl-config was found, let's use it
if test "${GSL_CONFIG}" != ""; then
# Use gsl-config for header and linker arguments
GSL_CFLAGS=`${GSL_CONFIG} --cflags`
GSL_LIBS=`${GSL_CONFIG} --libs`
else
AC_MSG_ERROR([gsl-config not found, is GSL installed?])
fi
# Now substitute these variables in src/Makevars.in to create src/Makevars
AC_SUBST(GSL_CFLAGS)
AC_SUBST(GSL_LIBS)
AC_OUTPUT(src/Makevars)
I then run autoconf in testpackage directory in order to get configure file, which in turn converts Makevars.in to Makevars when running R CMD INSTALL.
There are a few CRAN packages using the GSL, and/or our RcppGSL bindings. Here is what I do in one of these (my RcppZiggurat package):
PKG_CPPFLAGS = -I. -I../inst/include
## Use the R_HOME indirection to support installations of multiple R version
PKG_LIBS = `$(R_HOME)/bin/Rscript -e "RcppGSL:::LdFlags()"`
That is the entire /src/Makevars. You can trivially add the same OpenMP variable from R. This does of course create a dependency on RcppGSL (as I already use it in RcppZiggurat). Else you can look into the R/init.R of RcppGSL and see how it tries to talk to gsl-config and store those values. You can do the same in src/Makevars -- it is just basic Make usage and nothing Rcpp specific.
I want to create a dll dynamic library from a C source code so that I can load and use it in R. I am now using
R CMD SHLIB foo.c
in Windows 7 command line. But nothing happened. There is no error message but no dll file was created.
What's wrong with what I have done? Thank you.
I am sorry if my question is not very clear. But I figured it out how to get things work and possible mistakes. Hopefully it will be useful for someone. Here are the steps:
Install R (latest version is 3.0.0 now). Make sure to add R bin folder to PATH
Install the latest version of Rtools Here. Make sure to add "c:\Rtools\bin;c:\Rtools\gcc-4.6.3\bin;" to PATH
Write your C code, saved in foo.c
In Windows command window, type
R CMD SHLIB foo.c
then you should have a foo.dll file then you can call it in R. Note that the foo.dll created under 64bits R can only be loaded into 64bits R. If you try to load in 32bits R, you will get error messages.
Exactly what do you mean by "nothing happened"? Is R in your path?
What does R --version reveal? How about R CMD config CC and R CMD config CFLAGS?
Lastly, if you had Rcpp installed (and your toolchain was correct, including PATH settings and all the rest) the you could do things on the fly a la
R> library(Rcpp)
R> cppFunction('double foo(double x) { return std::sqrt(x); }')
R> foo(4)
[1] 2
R> foo(4.2)
[1] 2.04939
R> unclass(foo)
function (x)
.Primitive(".Call")(<pointer: 0x7f251ba76530>, x)
R>
Here we used cppFunction() (and a bunch of tricks inside Rcpp) to compile, link and load
a simple (and pretty useless...) C(++) function which takes a square root.
The (R) program I'm writing is at one point able to write C source code files containing OpenMP instructions in order to speed up the resulting program (these files mainly contain a set of differential equations whose results are written to an array - as these steps can be executed independently, I thought it to be a good idea to parallelize them using omp sections). As the files generated this way are supposed to be used in another part of my program I also use R to compile them using system(R CMD SHLIB...) at runtime, as this approach seemed to have the advantage that, using R CMD SHLIB, no specific compiler would need to be imposed on the user.
The problem I'm now facing is that I can't pass the -fopenmp (or -openmp) compiler directive to R CMD SHLIB and it is not possible to use a Makevars file providing additional compiler flags (or ideally $SHLIB_OPENMP_CFLAGS) when not building an R package - which I'm not doing in this case, so R CMD SHLIB compiles the file I give it. Without OpenMP paralellization, however, as I see no way how to pass the according flags to SHLIB in this situation.
Is there any possibility to use R CMD SHLIB for this task anyway or will I have to sacrifice portability by internally specifying a compiler for OpenMP compilation?
You can also do it in R with:
system("R CMD COMPILE filename.c CFLAGS=-fopenmp")
system("R CMD SHLIB filename.o")
If you must use R CMD SHLIB as opposed to a Makefile or package, I think you want to modify an environment variable such as PKG_CPPFLAGS or PKG_CXXFLAGS, which you can from inside R via Sys.setenv().
R itself now uses OpenMP and the compiler option you desire is available on recent R systems:
edd#max:~$ grep OPENMP /etc/R/Makeconf
SHLIB_OPENMP_CFLAGS = -fopenmp
SHLIB_OPENMP_CXXFLAGS = -fopenmp
SHLIB_OPENMP_FCFLAGS = -fopenmp
SHLIB_OPENMP_FFLAGS = -fopenmp
edd#max:~$
That's from a standard R 2.15.1 on a Debian / Ubuntu system.