My lua function looks like below. The parameter "scandate" is pased from c++ to the lua function. The printed output of the first line shows the date, and thereafter, any operation on the string indicates the string suddenly became null or empty.
function DoCustomLookup(wkItem,wkfId,wkevid,lookupTableID,scandate,lookuptext,lookupval,evtAlertText,newvalue,xtraFld1,xtraFld2,xtraFld3,xtraFld4,newStatus,newStatusDesc,errFlags)
local rslt = "Script error"
print (scandate)
local scYY = scandate.sub(1,4)
local scMM = scandate.sub(7,2)
local scDD = scandate.sub(10,2)
print (scYY)
print (scMM)
print (scDD)
local scandt = #scandate
print (scandt)
scYY,scMM, scDD = scandate.match("(%d+)%-(%d+)%-(%d+)%s.+")
...
end
Here is the console output:
2015-12-10 01:00:02
0
19
Workflow script error. Line :17: bad argument #2 to 'match' (string expected, got no value)
So it appears to me that the string simply vanishes in thin air.
Can someone please explain what is going on and how I can keep the string? The strange thing is that substrings do not work, but the string length still prints 19. Then match also keeps failing (That is why I tried the substr as alternative)
Here is my code calling it from c++. You will notice I copy the date to a temporary buffer. I thought maybe the std::string.c_str() maybe got out of scope, but it did not change wheter I pass the date as std::string or from a c buffer.
bool LuaScript::DoCustomLookup(int wkItem, int wkfId, int wkevid, const int lookupTableID, const std::string scantime,
const std::string& lookuptext, const std::string& lookupval, const std::string evtAlertText,
std::string& newvalue,
const std::string xtraFld1, const std::string xtraFld2, const std::string xtraFld3, const std::string xtraFld4,
int& newStatus, std::string& newStatusDesc, AlertFlags& errFlags, std::string& errMsg)
{
errMsg = "";
char **date**[50];
sprintf(date, "%s", scantime.c_str());
lua_getglobal(L, "DoCustomLookup"); // get function
lua_pushinteger(L, wkItem); // push parameter on call stack
lua_pushinteger(L, wkfId); // push parameter on call stack
lua_pushinteger(L, wkevid); // push parameter on call stack
lua_pushinteger(L, lookupTableID); // push parameter on call stack
lua_pushstring(L, **date**); // push parameter on call stack
lua_pushstring(L, lookuptext.c_str()); // push parameter on call stack
lua_pushstring(L, lookupval.c_str()); // push parameter on call stack
lua_pushstring(L, evtAlertText.c_str()); // push parameter on call stack
lua_pushstring(L, newvalue.c_str()); // push parameter on call stack
lua_pushstring(L, xtraFld1.c_str()); // push parameter on call stack
lua_pushstring(L, xtraFld2.c_str()); // push parameter on call stack
lua_pushstring(L, xtraFld3.c_str()); // push parameter on call stack
lua_pushstring(L, xtraFld4.c_str()); // push parameter on call stack
lua_pushinteger(L, newStatus); // push parameter on call stack
lua_pushstring(L, newStatusDesc.c_str()); // push parameter on call stack
lua_pushinteger(L, errFlags); // push parameter on call stack
int rslt = lua_pcall(L, 16, 1, 0);
Thank you
Related
I'm computing some heavy recursive function (let's say Fibonacci for the following code)
I have two versions :
- first one, vanilla recursive (uncommenting "if(false)" )
- the second one, using the process.nextTick every 5 calls in order to let other code run (uncommenting "if(n%5==0)" )
now running first one gets me a "RangeError: Maximum call stack size exceeded"
while running the second one provides me with a nice "196418"
here's the code. Could you tell me what's going on, because I can't believe that process.nextTick is cleaning the stack.
'use strict';
function fibo_cb( n, cb ){ fibo_rec( n, (res) => cb( res ) ); }
function fibo_rec( n, ret ){
if( n<2 ){
ret( 1 );
} else {
let rr = (res_1) => { return (res_2) => ret(res_1+res_2) };
let r = (res_1) => fibo_rec( n-2, rr(res_1) );
//if(false){ //no tick
if(n%5==0){ //do tick, once every 5
process.nextTick( () => fibo_rec( n-1, r ) );
} else {
fibo_rec( n-1, r );
}
}
}
fibo_cb( 26, console.log );
The JavaScript code is executed by putting all the code in Call Stack by creating scopes at function level. Since JavaScript is single threaded(apart from Asynchronous tasks), starting from Global level each scope is put into the call stack one by one until it reaches all the functions. Once the function gets completed it is popped out of the Call Stack.
In case of Recursive Functions, for each recursive call a function is pushed to Call Stack. So when there are large number of recursive calls the Call Stack gets full since a maximum limit is fixed for Call Stack.
Any Asynchronous Task scheduled using process.nextTick waits till call stack is empty and takes each callback from the Event Queue and pushes it to Call Stack. This happens repeatedly till all the recursive callbacks are finished.
Since Call Stack is emptied each time the is no "RangeError: Maximum call stack size exceeded" observed.
I am new to node.js and very inexpert when it comes to async processing.
I have a list of functions in an array, which I need to call asynchronously when a message arrives. I planned to use process.nextTick to schedule the calls. This is my (simplified) code:
// These are example message handlers
// All have to be called on every message
function fn1( msg ) { console.log( "fn1: " + msg ) };
function fn2( msg ) { console.log( "fn2: " + msg ) };
function fn3( msg ) { console.log( "fn3: " + msg ) };
// the functions to be called are saved in a list
var fns = [ fn1, fn2, fn3 ];
// function to schedule async callbacks to every
// function in the list.
function multicall( msg ){
// schedule the call back to each function
for( var ix = 0; ix < fns.length; ix++ ){
var fn = fns[ix];
process.nextTick( function() {
// call the nth function with the message
fn( msg );
}
);
}
}
// now make the call to schedule callbacks
console.log( "start" );
multicall( "information" );
console.log( "end" );
The calls are queued as expected, but the problem is that when the calls are made, they are all to the last function, instead of one call to each function. Presumably this is because the call to fn( msg ) actually references the value of the variable fn at the time of the call, not at the time that the function is was scheduled. The calls are therefore all made to the last function in the list:
S:\test>node asyncTest
start
end
fn3: information
fn3: information
fn3: information
I have tried various approaches but can't seem to get round this problem of the difference between the function referenced when the call is scheduled, and the function referenced when the call is executed.
EDIT - - - -
Although I accept that #jishi's answer below is better, I inadvertently found another answer to this problem, which is to use let fn = fns[ix]; instead of var fn = fns[ix];. When using let, the for loop creates a completely new variable on each iteration, so the value set in one cycle is not overwritten by the value set in the next cycle. I hadn't previously understood that the scope of a let variable is limited to each specific execution of the code block, not just by the static lexical structure of the code.
That's because the fn variable will be in scope for all of the scheduled calls, and you actually change fn.
You should just send in the reference of the function to the nextTick (and maybe rather use setImmediate()) and bind the variable that you want the function to be executed with, something like this:
process.nextTick(fn.bind(null, msg));
This will schedule the function currently assigned to fn, with null as this reference, and the current value of msg as first argument to the function.
With setImmediate, I think you can do this:
setImmediate(fn, msg)
Because first argument is function, and the following arguments are arguments for the function that will be used when invoking (similar to bind())
In my example, I actually schedule the function as a reference, whereas in your example, you are scheduling an anonymous function that lives in the same scope as multicall(), meaning that any changes in the multicall scope, will affect execution of your anonymous function.
Before bind() existed, you had to sort of declare a function, send in the variables you wanted to be set when execution the function, and then return a new function from that. Very cumbersome, and I argue that should be avoided since the bind() approaches makes it in a much neater way.
I am writing a LKM that hooks a function with a custom function.
To achieve this I am modifying the function's prologue with
mov rax, <custom_func_addr> // Intel syntax.
jmp rax
The exact opcode is : "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe0" // 8 '\x00' are replaced with actual address.
The code works fine.say I hook vfs_read(), It works accordingly.
The is one case I have observed in which hooking fails :
void foo(char *func) {
unsigned long addr = get_sym_addr(func); // gets the address of function.
DEBUG("function %s addr : %lu\n", func, addr);
hook((void*)addr, &test_func_hooked); // hook it with custom function.
void (*test_func_orig) (int) = addr; // get ptr to the function.
test_func_orig(20); // call through func ptr.
test_func(10); // call function directly.
}
// defined in same file.
void test_func(int a) {
printk("a = %d\n", a);
}
However Hooking happens properly when function gets called using func ptr.
and, If I directly call the function as - test_func(10), hook is not called.
Is there anything I am missing here ? I have tested the module by hooking vfs_read() , whenever a 'read' comes on any file, hook get called. Only this particular case where function to hook is in the same file, It is not working.
I am writing a custom Node.js addon. Everything works dandy except for the use of callbacks. I have a method in a DLL that requires registering a C++ function callback - it takes a function, and then calls it when it receives new data, which is simple enough. What I'd like to do is in my .cc file, pass a local method through, and when that method is triggered, call the JavaScript callback. Calling the JavaScript callback on it's own, and saving the callback and calling it later works fine.
in my addon.cc, I have a method that does nothing except call a saved callback:
static int __stdcall ReadCallback(RESULT* pResult){
const unsigned argc = 1;
v8::Local<v8::Value> argv[argc] = { Nan::New("bah").ToLocalChecked() };
Nan::MakeCallback(Nan::GetCurrentContext()->Global(), callback, argc, argv);
return 0;
}
I have an exposed node method that is callable:
void RunCallback(const Nan::FunctionCallbackInfo<v8::Value>& info) {
PipsLibrary::Functions::RegisterReadCallback(ReadCallback);
v8::Local<v8::Function> cb = info[0].As<v8::Function>();
callback = cb;
}
All of my other node methods calling through to the external C++ .DLL work, it's just passing this function as an argument from the .cc throws an error on run, "Uncaught Error: The specified procedure could not be found."
Not sure what the problem is, or if I can actually specify a method in the .cc file to pass through to C++ as a callback.
I'm writing a asynchronous Node Addon, but I have been struggling to figure out if I need to use a HandleScope in the "After" function that calls the client JavaScript callback. I've seen examples showing with and without new scopes, but never any explanation why. Here is an example:
void asyncWorkAfter(uv_work_t* req) {
HandleScope scope; // <-- Do you need a new scope?
const int argc = 1;
Local<Value> foo = String::New("foo");
Local<Value> argv[] = { foo };
// assume I got my callback function out of req
callback->Call(Context::GetCurrent()->Global(), argc, argv);
callback.Dispose();
// if i use a new HandleScope, what happens to argv when we go out of scope?
// Do i need to do something like a scope.Close() to copy argv to the parent scope?
}
Do you need/want a HandleScope when you call the callback?
What happens to argv in the example if you do use a new HandleScope?
String::New("foo") will allocate something on heap and return a handle, so you need to free the memory referenced by this handle some how. If you attach them to a HandleScope v8 will do that for you once all references are counted to zero.
Local handles are held on a stack and are deleted when the appropriate
destructor is called. These handles' lifetime is determined by a
handle scope, which is often created at the beginning of a function
call. When the handle scope is deleted, the garbage collector is free
to deallocate those objects previously referenced by handles in the
handle scope, provided they are no longer accessible from JavaScript
or other handles.
https://developers.google.com/v8/embed