C和Lua - 将原生对象实例传递给原生Lua函数

问题描述:

传递给Lua以便Lua可以调用原生函数的C函数是静态函数,因此不涉及对象实例。C和Lua - 将原生对象实例传递给原生Lua函数

在我的应用程序中,我有多个会话。每个会话都在自己的线程上运行,拥有自己的数据和自己的脚本,并且会话N的脚本必须能够访问该会话的数据N.

问题是,当您注册本机C函数可以从Lua调用,我无法传递会话对象的实例以使其在静态Lua函数中可用。

一种可能性是可以将会话实例存储到静态变量中,该静态变量可以从静态C函数中调用(从Lua调用),但这看起来很脏并且需要可能会导致某些脚本挂起的同步。

第二种可能性可能是创建一个代表会话的Lua对象,并调用它的成员方法,这样在我的C函数中,我就可以访问代表会话的Lua对象(“t​​his”)并检索由此对象表示的实际本地会话实例。但我不知道该怎么做。

有没有办法在Lua中创建表示本地对象实例的Lua对象,以便本地Lua函数可以访问该本地对象实例?

+1

只是一个快速提示:“Lua的”是出了名,不是首字母缩略词。这就是为什么它被写成“Lua”,而不是“LUA”;)有关更多信息,请参阅http://www.lua.org/about.html#name :) –

由于每个会话都有自己的线程,为什么不将它们链接在一起? 每当你的函数被调用时,从当前线程获取会话。

你可能想看看有关userdata的手册。

+0

感谢您的帮助。虽然基于当前线程的retreiving实例看起来不是非常简单的。如果我找不到更优雅的东西,我会保留这个解决方案。 – Virus721

+0

你可以将C函数封装在Lua中,并使用coroutine.thread()存储所需的数据Lua端。这可能更好的做C端,但做到这一点可以工作。调用Func(...)的代码实际上是调用ActualCFunc(variableFromThread,...) – EinsteinK

由于“每个会话都在自己的线程上运行”,因此您可以简单地将会话数据保存为静态thread-local

通过userdata传输会话数据会更好,metatable绑定相关的函数,并且不依赖于静态内容。

作为最后的选择,让我们结合:将会话数据保存为用户数据/指针Lua-state-local

在所有情况下,您必须关心类实例的破坏,因为userdata以C风格释放,与线程数据相同。

+0

感谢您的帮助。我会尝试基于此做一些事情,并在文档中找到更多信息。此外,我不能使用线程本地,因为我使用C++作为Windows CE和Android的通用代码库,并且我无法使用C++ 11,因为我无法使用比2008更新版本的Visual Studio。 – Virus721

当您使用Lua注册C函数时,您可以将附加值存储为所谓的“upvalues”。然后,C函数可以检索这些值时,它被称为:

// ... 
// push session instance pointer 
lua_pushlightuserdata(L, (void*)get_current_session()); 
// create a closure with one upvalue 
lua_pushcclosure(L, my_static_C_function, 1); 
// ... (the resulting Lua function is at the stack top now) 

在静态的C函数可以访问实例数据是这样的:

static int my_static_C_function(lua_State* L) { 
    session_t* instance = (session_t*)lua_touserdata(L, lua_upvalueindex(1)); 
    instance->do_something(); 
    return 0; 
} 
+0

This将类似于我的答案中的最后解决方案,但“Lua函数本地”。如果他只需要一个函数需要会话数据,那么这是一个很好的答案,否则C闭包会产生一些成本,并将会话数据放入注册表中会更聪明。 – Youka

+0

@siffiejoe感谢您的帮助。这似乎接近我所需要的。我会继续阅读文档并使用它,除非我在阅读文档时找到更优雅的方式。 – Virus721

+0

@Youka只有当我需要从一个本地函数访问我的本地会话实例时,为什么这个解决方案会很好? – Virus721