簡體   English   中英

從c ++調用lua函數時如何使表和變量值保持不變?

[英]How to make table and variable values to persist when calling a lua function from c++?

我從c ++腳本調用lua函數。 在lua函數中,我需要根據我從C ++傳遞給函數的數據更新某些變量和表。 必須在連續循環中將數據傳遞給lua函數,並且每次對lua變量和表的連續更新都必須考慮先前更新所做的更改。 如何以健壯的方式實現這一目標? 一種笨拙的方式可能只是傳遞C和lua之間的值,或者重復保存和加載它們,但由於我的數據表預計會非常大,所以實際上可能不是一個好選擇。 請建議解決方案。

PS:我不能簡單地在lua中編寫整個代碼,因為C ++代碼是為了運行rosservices並訂閱rostopics。 我認為在lua中可能很難達到相同的效果,雖然有一個名為roslua的包裝顯然與ros indigo不相容。

 function test_upvalues(a)
 print(a)
 local x=10
 local function increment(t)
 x=x+t
 end
 --increment(a)
 print(x)
return(increment)
end

從C ++調用它

lua_getglobal(L, "test_upvalues");
lua_pushvalue(L, -1);

lua_pushnumber(L,2); //push a value to increment state
lua_call(L,1,0);

lua_pushvalue(L, -1);
lua_pushnumber(L,3); //push another value to increment state further
lua_call(L,1,0);

這里變量x是一個狀態,我希望在將它從C ++傳遞的值遞增之后保留它的狀態。 我沒有得到的是調用本地函數increment(t) 應該在外部lua功能或其他地方? 當我在外部lua函數中注釋掉行增量(t)時,我只得到2,10,3,10作為輸出,而在增量(t)上我只得到2,12,3,13。顯然靜態變量行為未正確實現。 我哪里錯了? 謝謝。

擴展使用upvalues來攜帶狀態,這里有一些偽代碼可以幫助你入門。

Lua函數工廠返回一個函數( myfunction ),它具有持久狀態作為upvalue( mystatemystate2 ):

function create_myfunction ()
   local mystate = {} -- initial value of state
   local mystate2 = 0 -- Can have more than one upvalue
   local function myfunction (args)
       -- modify mystate and mystate2 based on args here
   end
   return myfunction
end

使用Lua中的狀態創建myfunction實例:

called_from_c_function = create_myfunction();

從C創建myfunction的實例:

lua_getglobal(L, "create_myfunction");
lua_call(L, 0, 1); // Zero arguments, one result

在循環中從C調用此函數

// Assume myfunction is on the top of the stack
for (...) { // Loop
    lua_pushvalue(L, -1); // Copy function on stack (so we can use it again, as it gets consumed by the call)
    // Now push an argument to the function on the stack here
    lua_pushfoo(L, ...); // Just an example
    lua_call(L, 1, 0); // Call myfunction with 1 argument, returning 0
    // We should be stack-neutral at this point, with myfunction on top
}

如果有什么不清楚,請告訴我。 我正在對你要維護的狀態做一些假設,並且還有一些其他的東西可以通過一些額外的工作來處理(比如將狀態返回到C)。


附錄

在您的示例中,從C ++調用Lua代碼時,存在一些問題。 這是我相信你想要的:

lua_getglobal(L, "test_upvalues"); // Put factory function on stack
lua_pushnumber(L, 1); // Argument 'a' (not sure what you are using it for)
lua_call(L, 1, 1); // Call factory.  Consumes argument 'a', returns function 'increment'

lua_pushvalue(L, -1); // Copies 'increment' on stack
lua_pushnumber(L, 2); //push a value to increment state
lua_call(L,1,0); // Calls 'increment' function with increment

lua_pushvalue(L, -1); // Copies 'increment' on stack
lua_pushnumber(L, 3); //push another value to increment state further
lua_call(L,1,0); // Calls 'increment' function with increment

為了查看這些增量的結果,您需要在increment函數內打印它們。 工廠函數被調用一次。 它返回的函數被多次調用。

如果你想能夠設置初始狀態並在之后檢索值,你可能需要一個像這樣的lua函數:

function increment_factory(value)
  local function get_state()
    return value
  end
  local function increment(x)
    value = value + x
  end
  return get_state, increment
end

這里工廠函數返回兩個函數,一個用於遞增狀態,另一個用於檢索它。 valueget_stateincrement get_state (如果你想在每次增量之后獲得狀態的值,那么從increment返回它會更容易。)這將使用如下:

lua_getglobal(L, "increment_factory");
lua_pushnumber(L, INITIAL_STATE);
lua_call(L, 1, 2);  // One argument, two returned functions

lua_pushvalue(L, -1); // Copy 'increment'
lua_pushnumber(L, 2); // Push value to increment
lua_call(L, 1, 0);    // Call 'increment'

lua_pushvalue(L, -1); // Copy 'increment'
lua_pushnumber(L, 3); // Push value to increment
lua_call(L, 1, 0);    // Call 'increment'

lua_pushvalue(L, -2); // Copy 'get_state'
lua_call(L, 0, 1);    // Call 'get_state'

// Now the current state is on the top of the stack

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM