I'm loading a Lua script to be run multiple times and another Lua script that acts as a library that is supposed to be used by the first script.
Let HelloWorldAPI.lua :
function HelloWorld()
return "Hello world"
end
And SomeScript.lua :
HelloWorld()
I'm doing things in the following order :
L = luaL_newstate();
luaL_openlibs( L );
luaL_loadfile( L, "HelloWorldAPI.lua" );
luaL_loadfile( L, "SomeScript.lua" );
...
lua_pcall( L, 0, 0, 0 )
...
lua_pcall( L, 0, 0, 0 )
...
(some pieces of code were removed to keep it simple)
But I'm geting an error saying that I'm trying to call a nil value when calling the HelloWorld function.
Why ?
The function that I declared when the lib script was executed should be global and thus available in SomeScript.lua, right ?
Thank you.
luaL_loadfile(); loads and compiles a chunk, puts it on top of the stack, but does not execute it yet (so, after the first call to luaL_loadfile the function HelloWorld is not yet defined in the global lua state.
Then, you load the file SomeScript.lua, which is now on top of the stack. The call to lua_pcall now executes this chunk at the top, which tries to call the (not yet) defined function HelloWorld, resulting in the error you observe.
With this in mind, that would be the correct order:
luaL_loadfile( L, "HelloWorldAPI.lua" );
lua_pcall( L, 0, 0, 0 );
luaL_loadfile( L, "SomeScript.lua" );
lua_pcall( L, 0, 0, 0 );
However, to load and immediately execute a file you should use luaL_dofile:
luaL_dofile( L, "HelloWorldAPI.lua" );
luaL_dofile( L, "SomeScript.lua" );
luaL_loadfile leaves the compiled script as a function on the stack.
So, the function for SomeScript.lua is at the top, the function for HelloWorldAPI.lua is below it.
Related
I am loading Lua script with:
lua_State * L = lua_open();
luaL_openlibs(L);
const char lua_script[] = "function sum(a, b) return a+b; end print(\"_lua_\")";
int load_stat = luaL_loadbuffer(L,lua_script,strlen(lua_script),lua_script);
lua_pcall(L, 0, 0, 0);
Now I can call
lua_getglobal(L,"sum");
and get result from it on C-side
However, when I call lua_pcall, script is executed and it leads to output "_lua_" to console. Without lua_pcall, I cannot later access lua_getglobal. Is there any way around this? I dont want to call lua_pcall before setting "entry point" function via lua_getglobal.
If you can modify the script, a different approach to this is to pack your initialization code (the print and whatever else may be there) into a separate function, like so:
lua_State * L = lua_open();
luaL_openlibs(L);
const char lua_script[] = "function sum(a,b) return a+b end return function() print'_lua_' end";
int load_stat = luaL_loadbuffer(L,lua_script,strlen(lua_script),lua_script);
lua_pcall(L, 0, 1, 0); // run the string, defining the function(s)…
// also puts the returned init function onto the stack, which you could just leave
// there, save somewhere else for later use, … then do whatever you need, e.g.
/* begin other stuff */
lua_getglobal(L, "sum");
lua_pushinteger( L, 2 );
lua_pushinteger( L, 3 );
lua_pcall(L, 2, 1, 0);
printf( "2+3=%d\n", lua_tointeger(L,-1) );
lua_pop(L, 1);
/* end other stuff (keep stack balanced!) */
// and then run the init code:
lua_pcall(L, 0, 0, 0); // prints "_lua_"
Now, while you still have to run the chunk to define the function(s), the other initialization code is returned as a function which you can run at a later time / with a modified environment / … (or not at all, if it's unnecessary in your case.)
The function sum is not defined until you run the script because function definition is an assignment in Lua, and it needs to be executed.
So, there is no way to avoid running the script that defines sum. That is what lua_pcall does. You could use lua_call, but then you wouldn't be able to handle errors.
I'm a beginner in R and I'm trying to load a .dll file, named dll.dll, that's written in C, into R. It seems to work, now I want to use the functions that are stored in the .dll file and I encounter problems.
I've searched for a solution or other method in manuals, here and on google. Would be very thankful if I could get a suggestion of what to use or any idea!
My code:
setwd("C:/Users/MyUser/R")
dyn.load("dll.dll")
is.loaded("DLL_FUNK")
# For some reason True with capital letters, not in lower case
output <- .C("DLL_FUNK", in9 = as.integer(7))
#output # R Crashes before I can write this.
# R Crashes
# In outdata.txt: "in-value= 139375128"
The function should return a number, 1955. But I can't seem to get to that value. What am I doing wrong?
Update with code (Fortran runned as C), this is the code in dll.dll:
subroutine dll_funk(in9)
implicit none
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
!*** Declarations: variables, functions
!+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
integer(4) :: in9
!integer :: in9
! Definitions of variables in the external function calls
!!dec$ attributes c,alias :'dll_funk' :: dll_funk
!dec$ attributes dllexport :: dll_funk
!dec$ attributes value :: in9
open(194,file='outdata.txt')
write(194,*) 'in-value=', in9
! in9 = 1955
close(194)
end subroutine
!end function
So now when it runs, R crashes but before it writes to my file (outdata.txt) but it't not my number, maybe some kind of address...
Another question, do you recommend me to run the code with .C and from C run the Fortran code or is it better to run it with .Fortran with only Fortran code?
It seems like .Fortran have problem handling strings, or that's what I understood from: Interface func .C and .Fortran
Why did not you pass any arguments to your C function dll_function? When you use .C(), you have to pass function arguments as a list. .C() will return modified list. So, If you pass in nothing, you get nothing.
What does your C function dll_function looks like? Note that:
dll_function must be a void C function, with no return values. If this function should return something, it must return by modifying function arguments;
all function arguments of dll_function must be pointers.
Follow-up
The dll_function is only to test if I can get access to it.
You can use is.loaded() after dyn.load() to test whether you have access to the C function:
dyn.load("dll.dll")
is.loaded("dll_function") ## TRUE
Note that, is.loaded takes C function name, while dyn.load() takes .dll name. In general you can have multiple functions in a single .dll file. You can use is.loaded() to check either of them, to test whether shared library has been loaded successfully.
So if I want it to return something, I should give it an argument (of same type?)?
Yes. The other answer here does give a toy example. You can have a look at this answer I made half a month ago. At the bottom there is a summary of variable type.
When using .C, the extra arguments passed to .C are copied and passed on as pointers to the called c-function. This function can then modify the data pointer to by the pointers. The return value of the function is ignored by .C. So, you c-function should look something like:
void dll_function(int* result) {
/* Do some complicated computation that results in 1955 */
(*result) = 1955;
}
And your call from R:
.C("dll_function", integer(1))
An example with input (this calculates the sum of an integer vector; this example assumes that there are no missing values in vector):
void dll_function2(int* result, int* vector, int* length) {
int sum = 0;
for (int i = 0; i < (*length); ++i, ++vector) {
sum += (*vector)
}
(*result) = sum;
}
Called from R:
x <- c(1000, 900, 55)
.C("dll_function2", integer(1), as.integer(x), length(x))[[1]]
This issue I posted here is actually due to the configuration of the servers. The package actually has no issue related to R/C.
I am developing an R package using foreach to speedup the computation. To illustrate the structure of the package, I give a simplified R script and a C file below:
f3.R:
f3 = function(.lst){
cl <- makeCluster(2)
registerDoParallel(cl)
f1 <-function(x){
tmp <- .C("foo")
x
}
f2 <-function(x){
f1(x)
}
foreach(x=.lst, .verbose = TRUE ) %dopar% {
f2(x)
}
}
foo.c
#include <stdio.h>
#include <R.h>
extern "C" {
void foo() {
;
}
}
This package works very well on Mac OS, but throw an error message
automatically exporting the following variables from the local environment: f1, f2
numValues: 1, numResults: 0, stopped: TRUE
got results for task 1
accumulate got an error result
numValues: 1, numResults: 1, stopped: TRUE
not calling combine function due to errors
returning status TRUE
Error in { : task 1 failed - "C symbol name "foo" not in load table"
This is what I’ve tried:
add .export = c("foo"): doesn't help
move f1() and f2() to a separate R script and add .export = c("f1", "f2"): work on Mac OS, too, but doesn't help on linux
if I don't build a package, but load the functions above to the memory directly, then it works on both Mac OS and Linux
if no C function is called (note that in my example, the C code did nothing), then it works on both Mac OS and Linux. However, if I move f1() and f2() to separate R scripts and add .export = c("f1", "f2"), it fails on Linux again.
Most of the posts found from the internet suggested using .export to export R functions, but I didn't find anything about exporting C symbols.
I solved the problem by creating a package with all functions with a .C in it.
Then you add .packages = "yourpackage" and export all functions needed.
I have the following code:
// global variables
count = 0;
char arr[50][5];
main(){
// do something
}
init(){
count = 0;
memset (arr, 0, sizeof(arr));
}
I need to return 1 if init() is successful, but 0 if not. However, I can't see how init() can technically fail. How should I implement this error handler in init()?
There are 2 issues:
You don't need to return anything if you don't want to, just make the function void
Your init function is not needed as arr is already 0-initialized since it has static storage (global variable).
EDIT
basically main() can modify count and arr, and at some point i need to
re-initialize the global variables using init().
If the function can be called later on it would be useful to call it "reset", "reinit", "clear" etc. "init" makes the reader think it is only called once, at the beginning
According to the write-up i have to return 1 or 0 in init() depending
on whether there's an error...
In that case just say:
/* XXX No other return code is possible. */
return 0;
I'm embedding lua in my C application.
I'm pushing a variable into stack from C side, and want to retrieve it in the lua script itself.
What can I use to get the pushed value in the stack in the script file?
C code:
// ...
result = lua_load(L, luaByteCodeReader, file, "script", "bt");
lua_pushinteger(L, session_id);
if( lua_pcall(L, 1, 0, 0) != 0 )
// ...
In the Script I want to retrieve the session_id value
local session_id = ...
print "Start"
for i = 1, 10 do
print(i, session_id)
end
print "End"
Problem is you're passing parameters to the script loading, depending on your situation you may set a global value instead or call a function.
For instance, say you have a on_init function on your script:
function on_init(session_id)
...do something...
end
You can load the script as you're doing, then get the on_init function on top of the stack and call it with your parameter:
lua_getglobal(L, "on_init");
lua_pushnumber(L, session_id);
/* call the function with 1 arguments, return 0 result */
lua_call(L, 1, 0);
And it's a little bit cleaner.