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.
Related
In short, my question is: How do I build a DLL in Windows 11 using mingw-gcc that can be used as an external function for a Modelica simulation in OpenModelica?
I am able to get the simulation to compile and link, but as soon as it starts execution, the program returns exit code 0xFFFFFFFFC0000135, which I believe is caused by a problem with the DLL.
I have the following directory structure for the simulation and other files:
root
L ExternalFunctionTest.mo (model)
L Resources (folder)
L Include (folder)
L myExtLib.h (external function declaration)
L Library (folder)
L libMyExtLib.dll (build output for myExtLib.c)
L Src (folder)
L myExtLib.c (external function definition)
I have built the DLL using GCC in Windows 11 using gcc (mingw64, Rev5, Built by MSYS2 project 10.2.0) command:
gcc -fPIC -shared -o Resources/Library/libMyExtLib.dll Resources/Src/myExtLib.c
I have also tried adding the options -falign-functions -mstackrealign -msse2 -mfpmath=sse, which I noticed that OpenModelica uses when compiling its own source files, as well as adding -m64. I have also tried switching to use the same compiler used by OpenModelica in its tools/mingw64 subdirectory to build the DLL.
When I run the simulation, everything compiles and links properly, but the simulation crashes immediately with the message:
C:/ ... /modelica_workspace/ExternalFunctionTest.TestModel/TestModel.exe -port=49874 -logFormat=xmltcp -override=startTime=0,stopTime=1,stepSize=0.002,tolerance=1e-6,solver=dassl,outputFormat=mat,variableFilter=.* -r=C:/ ... /modelica_workspace/ExternalFunctionTest.TestModel/TestModel_res.mat -w -lv=LOG_STATS -inputPath=C:/ ... /modelica_workspace/ExternalFunctionTest.TestModel -outputPath=C:/ ... /modelica_workspace/ExternalFunctionTest.TestModel
Process crashed
Process crashed
Simulation process failed. Exited with code 0xffffffffc0000135.
A colleague was able to get everything to work in Linux using the following command to build a .so DLL:
gcc -Wall -fPIC -shared -o Resources/Library/libmyFunction.so Resources/Src/myFunction.c
I tried this using both Modelica v1.18.0 and v1.18.1 (64-bit).
If anyone can shed some light it would be greatly appreciated!
The contents of ExternalFunctionTest.mo:
package ExternalFunctionTest
model TestModel
Real x(start=1);
Real y(start=2);
equation
der(x) = 1;
y = testFunction(x);
end TestModel;
function testFunction
input Real x;
output Real y;
external "C" extFunction(x, y) annotation(Library="libMyExtLib", Include="#include \"myExtLib.h\"");
end testFunction;
end ExternalFunctionTest;
The contents of myExtLib.c:
#include "../Include/myExtLib.h"
void extFunction(const double input, double * const output)
{
*output = 2 * input;
}
The contents of myExtLib.h:
#ifndef MY_EXT_LIB_H__
#define MY_EXT_LIB_H__
void extFunction(const double input, double * const output);
#endif
Follow up:
The problem was related to an issue in OpenModelica version 1.18 where the DLL was not being added to the path prior to executing the simulation, as noted in the comments by Adrian Pop. By upgrading to the latest stable development release, 1.19.0, the problem resolved itself.
I'm trying to write a haskell module that wraps a bunch of c functions.
I want to be able to import this module like any other haskell module without referring to the c object files.
I can't find any examples about how to do this.
This is what I've tried. I have a c file "dumbCfunctions.c":
double addThree(double x) {
return x+3;
}
and a haskell file with a module defined in it "Callfunctions.hs"
module Callfunctions (
addThree
) where
import Foreign.C
foreign import ccall "addThree" addThree :: Double -> Double
main = print $ addThree 4
I can make an executable doing:
ghc --make -o cf_ex Callfunctions.hs dumbCfunctions.o
Which correctly gives me 7.
I can also import it into ghic by calling ghci with
shane> ghci dumbCfunctions.o
Prelude> :l Callfunctions.hs
[1 of 1] Compiling Callfunctions ( Callfunctions.hs, interpreted )
Ok, modules loaded: Callfunctions.
*Callfunctions> addThree 3
6.0
But I want to be able to treat it like any other module with out referring to "dumbCfunctions.o":
shane> ghci
Prelude> :l Callfunctions.hs
[1 of 1] Compiling Callfunctions ( Callfunctions.hs, interpreted )
Ok, modules loaded: Callfunctions.
*Callfunctions> addThree 3
But now I get the error
ByteCodeLink: can't find label
During interactive linking, GHCi couldn't find the following symbol:
addThree
This may be due to you not asking GHCi to load extra object files,
archives or DLLs needed by your current session. Restart GHCi, specifying
the missing library using the -L/path/to/object/dir and -lmissinglibname
flags, or simply by naming the relevant files on the GHCi command line.
Alternatively, this link failure might indicate a bug in GHCi.
If you suspect the latter, please send a bug report to:
glasgow-haskell-bugs#haskell.org
This makes sense because I haven't refereed to the object anywhere. So I must be able to do something better by first compiling the module, but I couldn't find out how to do this. I must be looking in the wrong places.
You can create a library through Cabal, and cabal install it.
This would link the C code inside your Haskell library. Later on, when you load the module, you will not need to manually load the C parts.
I am trying to Link R and C in windows while following the instructions on this web page
http://mcglinn.web.unc.edu/blog/linking-c-with-r-in-windows/
I have R, RTOOLS and TurboC4 all in separate folders in C drive. My system is 64bits but I have tried it on both 32 and 64 bit R.
I have written the following code in C
#include <R.h>
void hello(int *n)
{ int i;
for(i=0; i<=*n; i++){
Rprintf("hello, world!this is hell though I'm enjoying it\n");
}
}
and saved with name WORLD.C on separate file the path to which is
C:\TurboC4\TC\BIN
I have also written the following R code
hello2 <- function(n) {
.C("hello", as.integer(n))
}
hello2(5)
and save it with name WORLD.R.
Now I have to prepare my window. I have downloaded RTools33.exe from here https://cran.r-project.org/bin/windows/Rtools/
and set the environment variables manually through this command
PATH=c:\Rtools\bin;c:\Rtools\gcc-4.6.3\bin;c:\Program Files\R\R-3.2.2\bin\i386;
Then Reinstalled system
Before calling the C code in R I have to compile the C code in cmd. I write the following command to change the directory where WORLD.C is saved
cd C:\Users\TurboC4\TC\BIN
which is successful but when I try to compile
C:\Users\TurboC4\TC\BIN> R CMD SHLIB WORLD.c
I get the following error. " 'R' is not recognized as internal or external command, operable ". I have also tried to compile WORLD.C in C and got these two errors. "Unable to open #include R.h>" and "function Rprintf should have a prototype".
Setting Environment is a Problem
I think this is where I am facing problem. I have checked that Rtools33.exe is compatible with R 3.2.x and later. But I am getting the same error on CMD. I have tried different paths environments and have tried it with Different R versions like R- 3.2.2, R- 3.2.0, 2.15.3, 2.15.0. But when I write
"install.packages("RTools33") in any of these R version, I got the following warning message
Warning in install.packages :package ‘RTools33’ is not available (for R version
2.15.0)"
The reason for using different Rs is when you download RTOOLS folder there is a version file which says "Rtools Collection 3.3.0.1959". So I think maybe it a compatibility issue.
There are some instructions on Github page
https://github.com/stan-dev/rstan/wiki/Install-Rtools-for-Windows
"For installing Rtools, attention needs to be paid in a step where we can edit the system PATH so that the C++ compiler that is included in Rtools can be used by R. As indicated by the following step, we need to check this option (not manually edit the system PATH. Once the option is checked, system PATH would be edited to include important folders of Rtools by the installation process)."
So, I have uninstalled RTools and while reinstalling I have checked this option button as well and then retried but all in vein.
I have checked Sys.getenv('PATH') and got
c:\\\\\\\\Rtools\\\\\\\\gcc-4.6.3\\\\\\\\bin;c:\\\\\\\\RTools\\\\\\\\bin;
I have also tried by setting this path in
control pannel-> useraccountandfamilysafety->Useraccounts->change my
environment variable
and then creating new variable with above PATH.
I am still not able to direct R to C++ compiler. Can anybody please figure out what is my mistake?
This problem is now solved. There was just a minor mistake of defining the environment variable. The correct definition is as follows.
c:\Rtools\bin;c:\Rtools\gcc-4.6.3\bin;c:\Program Files\R\R-3.2.2\bin\i386;
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'm running Mathematica 8 on a MacOSX, trying to compile even the simplest program to C. Anything having to do with C simply doesn't work in Mathematica. I have GCC 4.2 installed; I've even reinstalled it multiple times with XCode. Here's what I'm doing and the errors I'm getting:
First, I always evaluate the command
Needs["CCompilerDriver`"]
If I set the compilation target to C,
c = Compile[ {{x}}, x^2 + Sin[x^2], CompilationTarget -> "C"];
I get an error that reads: Compile::nogen : A library could not be created from the compiled function.
If I try to create a library,
demoFile = FileNameJoin[{$CCompilerDirectory,"SystemFiles","CSource","createDLL_demo.c"}];
lib = CreateLibrary[{demoFile},"testLibrary"]
I get an message $Failed. Wolfram says that this is because I don't have a C compiler installed. I find that hard to believe because when I run
CCompilers[]
It tells me that I've got GCC installed: {{"Name" -> "GCC",
"Compiler" -> CCompilerDriver'GCCCompiler`GCCCompiler,
"CompilerInstallation" -> "/usr/bin", "CompilerName" -> Automatic}}
What's more, terminal says I have GCC installed too!! Any help would be appreciated. I'd really like to compile Mathematica to C.
In this answer I'll collect some debugging steps for similar problems, for future reference. Feel free to edit/improve them.
If compiling to C code does not work from Mathematica 8,
Check that you have a supported C compiler installed and it works (the obvious).
Note that the compiler does not necessarily have to be in the PATH, at least on Windows/Visual Studio it doesn't.
Check that Mathematica recognizes the compiler
<< CCompilerDriver`
CCompilers[]
will list the compilers known to Mathematica.
Check what commands Mathematica executes to compile the generated C code:
Compiler`$CCompilerOptions = {"ShellCommandFunction" -> Print};
Compile[{{x}}, x^2, CompilationTarget -> "C"];
Note that with "ShellCommandFunction" -> Print the commands will not be executed, so you'll need to re-set Compiler`$CCompilerOptions to {} after this step is complete to allow command execution again.
Check the output/errors from the compiler:
Compiler`$CCompilerOptions = {"ShellOutputFunction" -> Print};
Compile[{{x}}, x^2, CompilationTarget -> "C"];
These last two steps will hopefully give you enough clues to proceed. With this information you can check if the correct library / include paths are passed to the compiler (in the case of gcc/icc, look at the -L option which specifies library paths and the -I option which specifies include paths). Then check if the required include and library files are present at those paths.
If you get Compile::nogen, you can see the compiler output by setting ShellOutputFunction->Print right in the Compile expression:
c = Compile[ {{x}}, x^2 + Sin[x^2],
CompilationTarget -> {"C", "ShellOutputFunction"->Print}];
In general, this is how you can pass options to the underlying CreateLibrary call, by changing CompilationTarget->"C" to CompilationTarget->{"C", options}. Setting Compiler`$CCompilerOptions works too, but this technique has the advantage of not setting a global variable.
It is a shame that the only error you are seeing is $Failed, that's not terribly helpful; I wonder if perhaps there are some file or directory permissions problems?
I'm running on linux not Mac so I am not sure if my setup is "close enough" or not. On my machine your Compile command succeeds and generates a file .Mathematica/ApplicationData/CCompilerDriver/BuildFolder/blackie-desktop-5077/compiledFunction1.so in my home directory. Is there any way you can find a .Mathematica directory associated with your userid, and see if it exists and is writeable by mathematica?
Also, you could check to see if "gcc" is or is not being accessed by checking the file access time of /usr/bin/gcc before and after your call to Compile. From an operating system shell you can do ls -lu /usr/bin/gcc or from Mathematica perhaps Import["!ls -lu /usr/bin/gcc", "Text"]