简体   繁体   中英

How to change a C macro variable (preprocessor define directive) from inside an R session?

Questions

  1. Is it bad practice to compile shared libraries from inside an R session using system() or shell() then dynamically load them?
  2. Is there a "better" way (than the code below) to change the value of a macro variable in a C source file based on user input from an R session?

Background

Objective

In an R session, I want to create a function that

  1. changes the value of a macro variable in a template C source file,
  2. gives the edited source file a new name,
  3. compiles a shared library of the new program, and
  4. dynamically loads the new shared library into the current R session

Call the template C source file template.tmp and let it look something like:

...
#define VAR
...

(I don't plan on actually compiling template.tmp , hence the .tmp file extension. I merely use it as a template to create other source files where only the #define directive changes.)

Below is the R function, I created to do the steps above. For simplicity, I removed lines of code that declare correct path names or add portability to Windows and other Unix-alikes.

myfunc <- function(val){
  # create commands for system()
  subst_cmd <- paste0("sed 's/define VAR/define VAR ", val, "/' template.tmp > newprog.c")
  shlib_cmd <- paste0("R CMD SHLIB newprog.c")

  # submit commands to system()
  system(subst_cmd)
  system(shlib_cmd)

  # dynamically load shared library
  dyn.load(newprog.so)
}

Thus, myfunc(12345) will create a new C source file with the following lines, and will also compile it to a shared library and dynamically load it into the current R session.

...
#define VAR 12345
...

Motivation

I have a function where speed is very important as the function could be called thousands of times. Passing values to the function in my C source file tremendously slows down the speed when compared to using a #define preprocessor directive. My thinking was to some how edit the file within R then compile it and load it into the R session. But I do not know if this is good practice or if there is another way to accomplish the same task. One problem I have already encountered occurs when I remote into a computer cluster where the login node has compiling capabilities but the computing nodes do not.

Disclaimer: I dont have much knowledege about R. I am answering this using my experiance of using C shared library.

Is it bad practice to compile shared libraries from inside an R session using system() or shell() then dynamically load them?

Yes it is not a good practise. As you say it may be called 1000s of time changing the file and compiling every time is not a good option.

Is there a "better" way (than the code below) to change the value of a macro variable in a C source file based on user input from an R session?

If the only requirement is changing the value of a macro then why not convert it to a variable and pass that variable when calling the function in dynamically loaded library?

Consider following example:(The code below is for dynamic library)

foo.h

#ifndef foo_h__
#define foo_h__

extern void foo(int var);

#endif  // foo_h__

foo.c

#include <stdio.h>
int global_var;

void foo(int var)
{
    global_var= var;
}

Call the above function from R by passing the desired value of var to foo function. (I hope you know how to do this)

I don't plan on actually compiling template.tmp, hence the .tmp file extension. I merely use it as a template to create other source files where only the #define directive changes.

I suggest not to do this. Even if you have more then one such macros you can still use above logic to handle it. My suggestion is to compile the library once and then call initialisation function (foo in above example) passing it the required values. This will also avoid loading the library multiple times and hence make it efficient. This is better then what ur doing currently and easy to maintain and document.

File operations are inherently slow if you are concerned about speed and efficiency. Your program may some day become large hence compiling it for every function call will further add some delay in execution. Its bad idea to compile the library every time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM