Related
I have a binary file (ELF) that I don't write, but I want to use 1 function from this binary (I know the address/offset of the function), that function not exported from the binary.
My goal is to call this function from my C code that I write and compile this function statically in my binary (I compile with gcc).
How can I do that please?
I am going to answer the
call to this function from my c code that I write
part.
The below works under certain assumptions, like dynamic linking and position independent code. I haven't thought for too long about what happens if they are broken (let's experiment/discuss, if there's interest).
$ cat lib.c
int data = 42;
static int foo () { return data; }
gcc -fpic -shared lib.c -o lib.so
$ nm lib.so | grep foo
00000000000010e9 t foo
The above reproduces having the address that you know. The address we know now is 0x10e9. It is the virtual address of foo before relocation. We'll model the relocation the dynamic loader does by hand by simply adding the base address at which lib.so gets loaded.
$ cat 1.c
#define _GNU_SOURCE
#include <stdio.h>
#include <link.h>
#include <string.h>
#include <elf.h>
#define FOO_VADDR 0x10e9
typedef int(*func_t)();
int callback(struct dl_phdr_info *info, size_t size, void *data)
{
if (!(strstr(info->dlpi_name, "lib.so")))
return 0;
Elf64_Addr addr = info->dlpi_addr + FOO_VADDR;
func_t f = (func_t)addr;
int res = f();
printf("res = %d\n", res);
return 0;
}
int main()
{
void *handle = dlopen("./lib.so", RTLD_LAZY);
if (!handle) {
puts("failed to load");
return 1;
}
dl_iterate_phdr(&callback, NULL);
dlclose(handle);
return 0;
}
And now...
$ gcc 1.c -ldl && ./a.out
res = 42
Voila -- it worked! That was fun.
Credit: this was helpful.
If you have questions, feel free to read the man and ask in the comments.
As for
compile this function statically in my binary
I don't know off the bat. This would be trickier. Why do you want that? Also, do you know whether the function depends on some data (or maybe it calls other functions) in the original ELF file, like in the example above?
I have a shared library, say somelib.so, which uses ioctl from libc (according to objdump).
My goal is to write a new library that wraps around somelib.so and provides a custom ioctl. I want to avoid preloading a library to ensure that only the calls in somelib.so use the custom ioctl.
Here is my current snippet:
typedef int (*entryfunctionFromSomelib_t) (int par, int opt);
typedef int (*ioctl_t) (int fd, int request, void *data);
ioctl_t real_ioctl = NULL;
int ioctl(int fd, int request, void *data )
{
fprintf( stderr, "trying to wrap ioctl\n" );
void *handle = dlopen( "libc.so.6", RTLD_NOW );
if (!handle)
fprintf( stderr, "Error loading libc.so.6: %s\n", strerror(errno) );
real_ioctl = (ioctl_t) dlsym( handle, "ioctl" );
return real_ioctl( fd, request, data);
}
int entryfunctionFromSomelib( int par, int opt ) {
void *handle = dlopen( "/.../somelib.so", RTLD_NOW );
if (!handle)
fprintf( stderr, "Error loading somelib.so: %s\n", strerror(errno) );
real_entryfunctionFromSomelib = entryfunctionFromSomelib_t dlsym( handle, "entryfunctionFromSomelib" );
return real_entryfunctionFromSomelib( par, opt );
}
However, it does not in work in the sense that the calls to ioctl form somelib.so are not redirected to my custom ioctl implementation. How can I enforce that the wrapped somelib.so does so?
======================
Additional information added after #Nominal Animal post:
Here some information from mylib.so (somelib.so after edit) obtained via readelf -s | grep functionname:
246: 0000000000000000 121 FUNC GLOBAL DEFAULT UND dlsym#GLIBC_2.2.5 (11)
42427: 0000000000000000 121 FUNC GLOBAL DEFAULT UND dlsym##GLIBC_2.2.5
184: 0000000000000000 37 FUNC GLOBAL DEFAULT UND ioctl#GLIBC_2.2.5 (6)
42364: 0000000000000000 37 FUNC GLOBAL DEFAULT UND ioctl##GLIBC_2.2.5
After 'patching' mylib.so it also shows the new function as:
184: 0000000000000000 37 FUNC GLOBAL DEFAULT UND iqct1#GLIBC_2.2.5 (6)
I 'versioned' and exported the symbols from my wrap_mylib library for which readelf now shows:
25: 0000000000000d15 344 FUNC GLOBAL DEFAULT 12 iqct1#GLIBC_2.2.5
63: 0000000000000d15 344 FUNC GLOBAL DEFAULT 12 iqct1#GLIBC_2.2.5
However, when I try to dlopen wrap_mylib I get the following error:
symbol iqct1, version GLIBC_2.2.5 not defined in file libc.so.6 with link time reference
Is that maybe because mylib.so tries to dlsym iqct1 from libc.so.6 ?
If binutils' objcopy could modify dynamic symbols, and the mylib.so is an ELF dynamic library, we could use
mv mylib.so old.mylib.so
objcopy --redefine-sym ioctl=mylib_ioctl old.mylib.so mylib.so
to rename the symbol name in the library from ioctl to mylib_ioctl, so we could implement
int mylib_ioctl(int fd, int request, void *data);
in another library or object linked to the final binaries.
Unfortunately, this feature is not implemented (as of early 2017 at least).
We can solve this using an ugly hack, if the replacement symbol name is exactly the same length as the original name. The symbol name is a string (both preceded and followed by a nul byte) in the ELF file, so we can just replace it using e.g. GNU sed:
LANG=C LC_ALL=C sed -e 's|\x00ioctl\x00|\x00iqct1\x00|g' old.mylib.so > mylib.so
This replaces the name from ioctl() to iqct1(). It is obviously less than optimal, but it seems the simplest option here.
If you find you need to add version information to the iqct1() function you implement, with GCC you can simply add a line similar to
__asm__(".symver iqct1,iqct1#GLIBC_2.2.5");
where the version follows the # character.
Here is a practical example, showing how I tested this in practice.
First, let's create mylib.c, representing the sources for mylib.c (that the OP does not have -- otherwise just altering the sources and recompiling the library would solve the issue):
#include <unistd.h>
#include <errno.h>
int myfunc(const char *message)
{
int retval = 0;
if (message) {
const char *end = message;
int saved_errno;
ssize_t n;
while (*end)
end++;
saved_errno = errno;
while (message < end) {
n = write(STDERR_FILENO, message, (size_t)(end - message));
if (n > 0)
message += n;
else {
if (n == -1)
retval = errno;
else
retval = EIO;
break;
}
}
errno = saved_errno;
}
return retval;
}
The only function exported is myfunc(message), as declared in mylib.h:
#ifndef MYLIB_H
#define MYLIB_H
int myfunc(const char *message);
#endif /* MYLIB_H */
Let's compile the mylib.c into a dynamic shared library, mylib.so:
gcc -Wall -O2 -fPIC -shared mylib.c -Wl,-soname,libmylib.so -o mylib.so
Instead of write() from the C library (it's a POSIX function just like ioctl(), not a standard C one), we wish to use mywrt() of our own design in our own program. The above command saves the original library as mylib.so (while naming it internally as libmylib.so), so we can use
sed -e 's|\x00write\x00|\x00mywrt\x00|g' mylib.so > libmylib.so
to alter the symbol name, saving the modified library as libmylib.so.
Next, we need a test executable, that provides the ssize_t mywrt(int fd, const void *buf, size_t count); function (the prototype being the same as the write(2) function it replaces. test.c:
#include <stdlib.h>
#include <stdio.h>
#include "mylib.h"
ssize_t mywrt(int fd, const void *buffer, size_t bytes)
{
printf("write(%d, %p, %zu);\n", fd, buffer, bytes);
return bytes;
}
__asm__(".symver mywrt,mywrt#GLIBC_2.2.5");
int main(void)
{
myfunc("Hello, world!\n");
return EXIT_SUCCESS;
}
The .symver line specifies version GLIBC_2.2.5 for mywrt.
The version depends on the C library used. In this case, I ran objdump -T $(locate libc.so) 2>/dev/null | grep -e ' write$', which gave me
00000000000f66d0 w DF .text 000000000000005a GLIBC_2.2.5 write
the second to last field of which is the version needed.
Because the mywrt symbol needs to be exported for the dynamic library to use, I created test.syms:
{
mywrt;
};
To compile the test executable, I used
gcc -Wall -O2 test.c -Wl,-dynamic-list,test.syms -L. -lmylib -o test
Because libmylib.so is in the current working directory, we need to add current directory to the dynamic library search path:
export LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH
Then, we can run our test binary:
./test
It will output something like
write(2, 0xADDRESS, 14);
because that's what the mywrt() function does. If we want to check the unmodified output, we can run mv -f mylib.so libmylib.so and rerun ./test, which will then output just
Hello, world!
This shows that this approach, although depending on very crude binary modification of the shared library file (using sed -- but only because objcopy does not (yet) support --redefine-sym on dynamic symbols), should work just fine in practice.
This is also a perfect example of how open source is superior to proprietary libraries: the amount of effort already spent in trying to fix this minor issue is at least an order of magnitude higher than it would have been to rename the ioctl call in the library sources to e.g. mylib_ioctl(), and recompile it.
Interposing dlsym() (from <dlfcn.h>, as standardized in POSIX.1-2001) in the final binary seems necessary in OP's case.
Let's assume the original dynamic library is modified using
sed -e 's|\x00ioctl\x00|\x00iqct1\x00|g;
s|\x00dlsym\x00|\x00d15ym\x00|g;' mylib.so > libmylib.so
and we implement the two custom functions as something like
int iqct1(int fd, unsigned long request, void *data)
{
/* For OP to implement! */
}
__asm__(".symver iqct1,iqct1#GLIBC_2.2.5");
void *d15ym(void *handle, const char *symbol)
{
if (!strcmp(symbol, "ioctl"))
return iqct1;
else
if (!strcmp(symbol, "dlsym"))
return d15ym;
else
return dlsym(handle, symbol);
}
__asm__(".symver d15ym,d15ym#GLIBC_2.2.5");
Do check the versions correspond to the C library you use. The corresponding .syms file for the above would contain just
{
i1ct1;
d15ym;
};
otherwise the implementation should be as in the practical example shown earlier in this answer.
Because the actual prototype for ioctl() is int ioctl(int, unsigned long, ...);, there are no quarantees that this will work for all general uses of ioctl(). In Linux, the second parameter is of type unsigned long, and the third parameter is either a pointer or a long or unsigned long -- in all Linux architectures pointers and longs/unsigned longs have the same size --, so it should work, unless the driver implementing the ioctl() is also closed, in which case you are simply hosed, and limited to either hoping this works, or switching to other hardware with proper Linux support and open-source drivers.
The above special-cases both original symbols, and hard-wires them to the replaced functions. (I call these replaced instead of interposed symbols, because we really do replace the symbols the mylib.so calls with these ones, rather than interpose calls to ioctl() and dlsym().)
It is a rather brutish approach, but aside from using sed due to the lack of dynamic symbol redefinition support in objcopy, it is quite robust and clear as to what is done and what actually happens.
I'm trying to learn CMake using an example project that calculates the fibonacci of a given number. My project originally included a single ".c" file and header. I was able to build with CMake and run without issue. Now I'm trying to learn how to link libraries by moving my fibnoacci function into a separate ".c" file which I compile into a linkable library using CMake. It builds without issue but throws a segmentation fault when I run it. My project structure is:
fib
|
*---MathFunctions
| |
| *----CMakeLists.txt
| |
| *----myfib.h
|
*---CMakeLists.txt
|
*---fib.c
|
*---fib.h
|
*---myfib.c
|
*---Config.in.h
The CMakeLists.txt under the MathFunctions folder is empty. All of the program logic is in fib.c and myfib.c. All of the build is in the top CMakeLists.txt
fib.c:
# include "stdio.h"
# include "stdlib.h"
# include "Config.h"
#include "myfib.h"
void internalfib(int num)
{
printf("Internally defined fib\n");
int a, b;
a = 0;
b = 1;
printf( "custom fib of %d", b );
for( int i = 0; i + a <= num; b = i ) {
i = a + b;
a = b;
printf( ", %d", i );
}
}
int main( int argc, char** argv) {
fprintf(stdout,"%s Version %d.%d\n",
argv[0],
VERSION_MAJOR,
VERSION_MINOR);
#ifdef SHOW_OWNER
fprintf(stdout, "Project Owner: %s\n", OWNER);
#endif
myfib(atof( argv[1] ));
printf("\n");
return EXIT_SUCCESS;
}
myfib.c:
# include "stdio.h"
# include "stdlib.h"
void myfib(int num)
{
printf("custom myfib");
int a, b;
a = 0;
b = 1;
printf( "custom fib of %d", b );
for( int i = 0; i + a <= num; b = i ) {
i = a + b;
a = b;
printf( ", %d", i );
}
}
CMakeLists.txt:
#Specify the version being used aswell as the language
cmake_minimum_required(VERSION 2.6)
#Name your project here
project(fibonacci)
enable_testing()
set (VERSION_MAJOR 1)
set (VERSION_MINOR 0)
configure_file (
"${PROJECT_SOURCE_DIR}/Config.h.in"
"${PROJECT_BINARY_DIR}/Config.h"
)
option (SHOW_OWNER "Show the name of the project owner" ON)
#Sends the -std=c99 flag to the gcc compiler
add_definitions(-std=c99)
include_directories("${PROJECT_BINARY_DIR}")
include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
add_subdirectory (MathFunctions)
add_library(MathFunctions myfib.c)
#This tells CMake to fib.c and name it fibonacci
add_executable(fibonacci fib.c)
target_link_libraries (fibonacci MathFunctions)
#test that fibonacci runs
add_test (FibonacciRuns fibonacci 5)
#Test the fibonacci of 5
add_test (FibonacciCompare5 fibonacci 5)
set_tests_properties (FibonacciCompare5 PROPERTIES PASS_REGULAR_EXPRESSION "1, 1, 2, 3, 5")
install (TARGETS fibonacci DESTINATION ${PROJECT_BINARY_DIR}/bin)
After running "..cmake" and "make" from the build folder I run:
~/dev/cworkshop/fib/build$ ./fibonacci
./fibonacci Version 1.0
Project Owner: Clifton C. Craig
Segmentation fault: 11
Where am I going wrong?
Are you actually sure you're getting a segfault because of your build system?
Your code requires input, and you do not check that input is given. From fib.c:26:
myfib(atof( argv[1] ));
If no arguments are given, your code will try to read data that you haven't provided (and segfault). If you run your code: ./fibonacci 3, you'll print myfib. I'm going to guess this is what your problem is.
Other things to consider:
when giving a portion of code, try to ensure that it's either minimal and complete, or accurately describes your problem. Large blocks of commented-out code are not relevant to the question, while in this case header files and Config.h.in (which are required to get your example to compile), are not provided.
myfib.c and myfib.h are in different folders. If myfib.c is part of the MathFunctions library, I'd put the sources into that subdirectory. This is explained in the tutorial I think you're following: this one, which has a CMakeLists.txt file containing the line:
add_library(MathFunctions mysqrt.cxx)
in the MathFunctions library.
As pointed out by #n.m in the comments, atof takes a float as input - the Fibonacci sequence is generated using an int (so atoi is more appropriate).
For your example, I would not use add_definitions to set the compiler flags. The better way to do it (project-wide) is to use set ( CMAKE_CXX_FLAGS "-O0 -g -Wall"). (There are lots of useful CMake Variables). While add_definitions works, it's not the best tool for the job you're doing. :)
i am having a macro whose definition runs into around 50 lines and has lot of 'if else' statements. This macro def'n appears in a .h file. I am running 'gdb in TUI mode', but when the execution reaches that macro, the code window goes blank and returns back only after the macro code gets executed. I want to see line by line execution of the full macro code. Please let me know how can that be done (one way is to replace the macro with its definition in the code and then recompile it. i don't want to use this option as there are several such macros in my code).
Any help will be greatly appreciated. looking forward to get the solution for this problem. Please let me know if there is some other way for this issue rather than the usage of preprocessed file ? i am having a code which runs into several hundred .c & .h files.
One option is to fully preprocess your C file, expanding all macros in it, and then compile the resulting preprocessed file.
For example, consider this simple C program:
// file: prep.c
#include <stdio.h>
#define MY_BIG_MACRO \
int i; \
printf("integers from 0 to 9:\n"); \
for (i = 0; i < 10; i++) \
printf("%d ", i); \
printf("\n");
int main(void)
{
MY_BIG_MACRO
return 0;
}
Compile it, saving the temporary files (including the preprocessed source code):
gcc -Wall -O2 -g -std=c99 prep.c -o prep.exe -save-temps
This should give you a preprocessed version of prep.c, prep.i (shortened for brevity):
# 1 "prep.c"
# 1 "C:\\MinGW\\msys\\1.0\\home\\Alex//"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "prep.c"
# 1 "c:\\mingw\\bin\\../lib/gcc/mingw32/4.6.2/../../../../include/stdio.h" 1 3
...
int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (const wchar_t * __restrict__,
const wchar_t * __restrict__, __gnuc_va_list);
# 3 "prep.c" 2
# 11 "prep.c"
int main(void)
{
int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) printf("%d ", i); printf("\n");
return 0;
}
Now you want to get rid of the #-lines. One way or another, if they are left in, they will affect the debug info. Surprisingly, that means that the macro won't appear expanded in gdb.
Thankfully, grep can help (I'm not a grep pro, so check whether the params are correct, but they seem to work for me on Windows with MinGW x86):
grep ^[^\#].*$ prep.i > prepi.c
This will give you a stripped version of prep.i in prepi.c:
typedef unsigned int size_t;
typedef short unsigned int wchar_t;
typedef short unsigned int wint_t;
...
int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (const wchar_t * __restrict__,
const wchar_t * __restrict__, __gnuc_va_list);
int main(void)
{
int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) printf("%d ", i); printf("\n");
return 0;
}
Now you can compile it:
gcc -Wall -O2 -g -std=c99 prepi.c -o prepi.exe
And run it in gdb:
gdb prepi.exe
Issue the following commands:
b main
r
l
This will execute the app until main() and list the source code related to the reached breakpoint:
(gdb) b main
Breakpoint 1 at 0x40643f: file prepi.c, line 184.
(gdb) r
Starting program: C:\MinGW\msys\1.0\home\Alex\prepi.exe
[New Thread 7340.0x20c4]
Breakpoint 1, main () at prepi.c:184
184 int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) pri
ntf("%d ", i); printf("\n");
(gdb) l
179 const wchar_t * __restrict__, __gnuc_va_list);
180 int __attribute__((__cdecl__)) __attribute__ ((__nothrow__)) vswscanf (c
onst wchar_t * __restrict__,
181 const wchar_t * __restrict__, __gnuc_va_list);
182 int main(void)
183 {
184 int i; printf("integers from 0 to 9:\n"); for (i = 0; i < 10; i++) pri
ntf("%d ", i); printf("\n");
185 return 0;
186 }
(gdb)
As you can see, the macro body is now in the plain view.
One small problem here is that multi-line macros (those continued with \) are expanded into a single line. I haven't found an option to expand them into multiple lines, but you can do that manually.
"One does not simply step into macros."
You still have a few options:
Use the preprocessor, as #WhozCraig recommended.
For a little less code bloat, convert your macros to functions and re-compile.
If you absolutely don't want to recompile and you're comfortable with assembly code you can use stepi to execute your macro one machine instruction at a time.
If all the above does not work, really you should go back to using printf/fprintf within your large macro.
I had to deal with a 300 lines MACRO, burried deep into the library. This was easier than compiling by hand and dealing with post-processed files.
What is the simplest possible C function for starting the R interpreter, passing in a small expression (eg, 2+2), and getting out the result? I'm trying to compile with MingW on Windows.
You want to call R from C?
Look at section 8.1 in the Writing R Extensions manual. You should also look into the "tests" directory (download the source package extract it and you'll have the tests directory). A similar question was previously asked on R-Help and here was the example:
#include <Rinternals.h>
#include <Rembedded.h>
SEXP hello() {
return mkString("Hello, world!\n");
}
int main(int argc, char **argv) {
SEXP x;
Rf_initEmbeddedR(argc, argv);
x = hello();
return x == NULL; /* i.e. 0 on success */
}
The simple example from the R manual is like so:
#include <Rembedded.h>
int main(int ac, char **av)
{
/* do some setup */
Rf_initEmbeddedR(argc, argv);
/* do some more setup */
/* submit some code to R, which is done interactively via
run_Rmainloop();
A possible substitute for a pseudo-console is
R_ReplDLLinit();
while(R_ReplDLLdo1() > 0) {
add user actions here if desired
}
*/
Rf_endEmbeddedR(0);
/* final tidying up after R is shutdown */
return 0;
}
Incidentally, you might want to consider using Rinside instead: Dirk provides a nice "hello world" example on the project homepage.
In you're interested in calling C from R, here's my original answer:
This isn't exactly "hello world", but here are some good resources:
Jay Emerson recently gave a talk on R package development at the New York useR group, and he provided some very nice examples of using C from within R. Have a look at the paper from this discussion on his website, starting on page 9. All the related source code is here: http://www.stat.yale.edu/~jay/Rmeetup/MyToolkitWithC/.
The course taught at Harvard by Gopi Goswami in 2005: C-C++-R (in Statistics). This includes extensive examples and source code.
Here you go. It's the main function, but you should be able to adapt it to a more general purpose function. This example builds an R expression from C calls and also from a C string. You're on your own for the compiling on windows, but I've provided compile steps on linux:
/* simple.c */
#include <Rinternals.h>
#include <Rembedded.h>
#include <R_ext/Parse.h>
int
main(int argc, char *argv[])
{
char *localArgs[] = {"R", "--no-save","--silent"};
SEXP e, tmp, ret;
ParseStatus status;
int i;
Rf_initEmbeddedR(3, localArgs);
/* EXAMPLE #1 */
/* Create the R expressions "rnorm(10)" with the R API.*/
PROTECT(e = allocVector(LANGSXP, 2));
tmp = findFun(install("rnorm"), R_GlobalEnv);
SETCAR(e, tmp);
SETCADR(e, ScalarInteger(10));
/* Call it, and store the result in ret */
PROTECT(ret = R_tryEval(e, R_GlobalEnv, NULL));
/* Print out ret */
printf("EXAMPLE #1 Output: ");
for (i=0; i<length(ret); i++){
printf("%f ",REAL(ret)[i]);
}
printf("\n");
UNPROTECT(2);
/* EXAMPLE 2*/
/* Parse and eval the R expression "rnorm(10)" from a string */
PROTECT(tmp = mkString("rnorm(10)"));
PROTECT(e = R_ParseVector(tmp, -1, &status, R_NilValue));
PROTECT(ret = R_tryEval(VECTOR_ELT(e,0), R_GlobalEnv, NULL));
/* And print. */
printf("EXAMPLE #2 Output: ");
for (i=0; i<length(ret); i++){
printf("%f ",REAL(ret)[i]);
}
printf("\n");
UNPROTECT(3);
Rf_endEmbeddedR(0);
return(0);
}
Compile steps:
$ gcc -I/usr/share/R/include/ -c -ggdb simple.c
$ gcc -o simple simple.o -L/usr/lib/R/lib -lR
$ LD_LIBRARY_PATH=/usr/lib/R/lib R_HOME=/usr/lib/R ./simple
EXAMPLE #1 Output: 0.164351 -0.052308 -1.102335 -0.924609 -0.649887 0.605908 0.130604 0.243198 -2.489826 1.353731
EXAMPLE #2 Output: -1.532387 -1.126142 -0.330926 0.672688 -1.150783 -0.848974 1.617413 -0.086969 -1.334659 -0.313699
I don't think any of the above has answered the question - which was to evaluate 2 + 2 ;). To use a string expression would be something like:
#include <Rinternals.h>
#include <R_ext/Parse.h>
#include <Rembedded.h>
int main(int argc, char **argv) {
SEXP x;
ParseStatus status;
const char* expr = "2 + 2";
Rf_initEmbeddedR(argc, argv);
x = R_ParseVector(mkString(expr), 1, &status, R_NilValue);
if (TYPEOF(x) == EXPRSXP) { /* parse returns an expr vector, you want the first */
x = eval(VECTOR_ELT(x, 0), R_GlobalEnv);
PrintValue(x);
}
Rf_endEmbeddedR(0);
return 0;
}
This lacks error checking, obviously, but works:
Z:\>gcc -o e.exe e.c -IC:/PROGRA~1/R/R-213~1.0/include -LC:/PROGRA~1/R/R-213~1.0/bin/i386 -lR
Z:\>R CMD e.exe
[1] 4
(To get the proper commands for your R use R CMD SHLIB e.c which gives you the relevant compiler flags)
You can also construct the expression by hand if it's simple enough - e.g., for rnorm(10) you would use
SEXP rnorm = install("rnorm");
SEXP x = eval(lang2(rnorm, ScalarInteger(10)), R_GlobalEnv);
I think you can't do much better than the inline package (which supports C, C++ and Fortran):
library(inline)
fun <- cfunction(signature(x="ANY"),
body='printf("Hello, world\\n"); return R_NilValue;')
res <- fun(NULL)
which will print 'Hello, World' for you. And you don't even know where / how / when the compiler and linker are invoked. [ The R_NilValue is R's NULL version of a SEXP and the .Call() signature used here requires that you return a SEXP -- see the 'Writing R Extensions' manual which you can't really avoid here. ]
You will then take such code and wrap it in a package. We had great success with using
inline for the
Rcpp unit tests (over 200 and counting now) and some of the examples.
Oh, and this inline example will work on any OS. Even Windoze provided you have the R package building tool chain installed, in the PATH etc pp.
Edit: I misread the question. What you want is essentially what the littler front-end does (using pure C) and what the RInside classes factored-out for C++.
Jeff and I never bothered with porting littler to Windoze, but RInside did work there in most-recent release. So you should be able to poke around the build recipes and create a C-only variant of RInside so that you can feed expression to an embedded R process. I suspect that you still want something like Rcpp for the clue as it gets tedious otherwise.
Edit 2: And as Shane mentions, there are indeed a few examples in the R sources in tests/Embedding/ along with a Makefile.win. Maybe that is the simplest start if you're willing to learn about R internals.