//This has a large number of steps, but I'm gonna post them all. This is all using native Lua 5 and the lua CAPI.
int CreateInstanceOfT(lua_State* L) {
new (lua_newuserdata(L, sizeof(T))) T(constructor args);
return 1;
}
int CallSomeFuncOnT(lua_State* L) {
if (lua_istable(L, 1)) { // If we're passed a table, get CData
lua_getfield(L, 1, "CData");
lua_replace(L, 1);
}
if (!lua_touserdata(L, 1))
lua_error(L); // longjmp out.
T& ref = *(T*)lua_touserdata(L, 1);
ref.SomeFunc(); // If you want args, I'll assume that you can pass them yourself
return 0;
}
int main() {
lua_State* L = luaL_newstate();
lua_pushcfunction(L, CreateInstanceOfT);
lua_setglobal(L, "CreateInstanceOfT");
lua_pushcfunction(L, CallSomeFuncOnT);
lua_setglobal(L, "CallSomeFuncOnT");
luaL_dofile(L, "something.lua");
lua_close(L);
}
-- Accompanying Lua code: semicolons are optional but I do out of habit. In something.lua
function CreateCInstance()
local Instance = {
CData = CreateInstanceOfT();
SomeFunc = CallSomeFuncOnT;
}
return Instance;
end
local object = CreateCInstance();
object:SomeFunc(); // Calls somefunc.
내가 노출이 용이하게하고, 상속을 만드는 방법, 그리고 그와 같은 방법에 대한 세부 사항의 다량 게시 할 수 - 당신은 하나 이상의 T를 노출 할 경우이 변경 필요합니다을 (내가 생각 가장 일반적인 솔루션은 간단한 struct { std::auto_ptr<void>, int type }
거래입니다. 그러나이 과정에 대해 이해하지 못한다면 출발점이되어야합니다.
Bascally, 먼저 Lua에 약간의 공간 (userdata)을 할당 한 다음 T를 넣으라고합니다. CallSomeFuncOnT가 생기면 먼저 테이블을 가지고 있는지 물어 봅니다 (루아 클래스는 테이블을 기반으로합니다. 객체 지향, 메타 테이블 등을 지원하기 때문에 테이블을 기반으로합니다). 그리고 userdata를 가져 와서 우리의 포인터로 변환합니다. 개체로 변환 한 다음 참조로 변환합니다. lua_touserdata는 무효 *를 제공한다는 것을 기억하십시오. 그래서 상대방의 상황에 대해 확신 할 수 있습니다. 그런 다음 somefunc를 호출하고 리턴합니다. Main에서는 함수를 전역 변수로 등록하면됩니다.
이제 Lua에서 CreateInstanceOfT를 호출하면 Lua 사용자에게 투명하게 T 생성자가 호출됩니다. 그런 다음 루아 초보자에게는 더 간단하게 테이블에 놓고 SomeFunc를 호출하여이 테이블을 전달합니다.
남자, 나는이 코드가 얼마나 짜증나는지 믿을 수 없다 : P – Puppy
나는 틀린가, 아니면 T의 소멸자가 결코이 기술을 사용하여 호출되지 않는다는 사실인가? 내가 이해하는 것처럼, 루아는 C++ 객체에 대해 아무것도 모르고'lua_newuserdata '에 의해 할당 된 것과 같이 단순히 제어하는 메모리에'free'를 호출합니다. –
나는 분명히 그 부분을 분명히 남겨 두었습니다. 아마 다른 많은 유용한 부분과 함께. – Puppy