다른 사고방식 으로 c 호출 lua 함수 실현
가장 간단 한 c 리 셋 lua 함수 에 대해 모두 가 비교적 잘 알 고 있 을 것 입 니 다. lua 의 전체 함수 호출 에 대해 luagetglobal 과 luacall 하면 됩 니 다. 그러나 이것 은 숙주 프로그램 에 죽은 lua 의 함수 이름 을 써 야 합 니 다. 결합 성 이 너무 강 합 니 다. 저 는 예전 에 실 현 된 이벤트 알림 방식 에 문제 가 있어 서 다른 방법 으로 실현 하고 싶 습 니 다.
그 후에 저 는 또 다른 방식, 즉 함수 명 등록 방식 을 사 용 했 습 니 다. lua 에 함 수 를 썼 고 이 함수 명 을 숙주 에 게 등 록 했 습 니 다. 숙주 는 특정한 조건 에서 이 함수 이름 의 함 수 를 호출 했 습 니 다.이러한 방식 은 결합 성 문 제 를 해결 하 였 으 나 사용 이 불편 하고 들 어 오 는 매개 변수 가 너무 많 으 며 문자열 의 일치 호출 은 약간의 성능 손실 이 있 습 니 다.
나중에 cocos2dx 에서 함수 인용 을 사용 하여 lua 의 함 수 를 호출 한 것 같 아서 정말 좋 은 방법 이 었 다.숙주 프로그램 은 특정 이벤트 에 등 록 된 모든 함 수 를 호출 하면 lua 함수 호출 을 완성 할 수 있 습 니 다. 결합 성 이 매우 작 기 때문에 디지털 참조 방식 으로 lua 함 수 를 호출 하 는 간단 한 방법 을 실현 하 였 습 니 다.
핵심 사상 은 lua 가 제공 하 는 레 지 스 트 에 table 을 추가 하 는 것 입 니 다. 이 table 의 key 는 이른바 lua 함수 이기 때문에 value 는 lua 함수 의 값 입 니 다. lua 함 수 를 호출 할 때마다 ref 에 따라 function 을 직접 찾 을 수 있 습 니 다. 그러면 이 lua 함 수 를 직접 호출 할 수 있 습 니 다.
다음은 한 걸음 한 걸음.우선 전체 레 지 스 트 에 table 을 등록 해 야 합 니 다.cocos2dx 에서 string 을 사용 하여 key 를 만 들 었 습 니 다. 여기 서 저 는 구름 바람 이 큰 신의 글 에 따라 lightuserdata 를 key 로 사 용 했 습 니 다. 그러면 key 의 색인 시간 이 조금 줄 어 들 것 입 니 다. number 를 key 로 사용 할 수 없다 는 것 을 기억 하 세 요. 이것 은 lua 에 의 해 보존 되 었 습 니 다.
//////////////////////////////////////////////////////////////////////////
// static light userdata key
static int s_nLuaFunctionRefKey = 0;
void* GetLuaFunctionRefKey()
{
return (void*)&s_nLuaFunctionRefKey;
}
// static lua function reference id
static int s_nLuaFunctionRefId = 0;
int GetLuaFunctionRefId()
{
return ++s_nLuaFunctionRefId;
}
여기 서 우 리 는 정적 변수의 주 소 를 key 로 사용 하고 int 를 ref 의 색인 생 성기 로 사용 합 니 다.
ref 와 func 를 기록 하기 위해 table 을 만 들 었 습 니 다.
void luaext_open(lua_State* L)
{
#ifdef _DEBUG
int nStackTop = lua_gettop(L);
#endif
// push key
lua_pushlightuserdata(L, GetLuaFunctionRefKey()); // stack: key
// push value
lua_newtable(L); // stack: key table
// set global table key
lua_rawset(L, LUA_REGISTRYINDEX); // stack:
#ifdef _DEBUG
assert(nStackTop == lua_gettop(L));
#endif
}
그리고 우리 가 실현 하고 자 하 는 것 은 바로 lua 함 수 를 이 표 에 등록 하 는 것 이다.간단 합 니 다. 이 table 의 값 을 설정 하면 됩 니 다.
int luaext_registerLuaFunction(lua_State* L, int _nFuncIndex)
{
if(_nFuncIndex < 0)
{
return 0;
}
if(!lua_isfunction(L, _nFuncIndex))
{
return 0;
}
// push key
lua_pushlightuserdata(L, GetLuaFunctionRefKey()); // stack: func ... key
// get ref table
lua_rawget(L, LUA_REGISTRYINDEX); // stack: func ... reftable
if (!lua_istable(L, -1))
{
return 0;
}
// push new key
int nRefId = GetLuaFunctionRefId();
lua_pushnumber(L, nRefId); // stack: func ... reftable key
// copy function value from stack
lua_pushvalue(L, _nFuncIndex); // stack: func ... reftable key value
// set key
lua_rawset(L, -3); // stack: func ... reftable
// pop table
lua_pop(L, 1);
return nRefId;
}
등록 을 했 으 니 반 등록 도 해 야 하고 간단 합 니 다. key = nil 을 설정 하면 됩 니 다.
void luaext_unregisterLuaFunctionByRefId(lua_State* L, int _nRefId)
{
#ifdef _DEBUG
int nStackTop = lua_gettop(L);
#endif
// push key
lua_pushlightuserdata(L, GetLuaFunctionRefKey()); // stack: func ... key
// get ref table
lua_rawget(L, LUA_REGISTRYINDEX); // stack: func ... reftable
if (!lua_istable(L, -1))
{
return;
}
// push the key
lua_pushnumber(L, _nRefId); // stack: reftable key
// push nil
lua_pushnil(L); // stack: reftable key nil
// set nil
lua_rawset(L, -3);
// pop reftable
lua_pop(L, 1);
#ifdef _DEBUG
assert(lua_gettop(L) == nStackTop);
#endif
}
이 반 등록 은 ref 에 따라 반 등록 한 것 입 니 다. 물론 func 에 따라 반 등록 을 해 야 할 수도 있 습 니 다. 실현 도 간단 합 니 다. table 을 옮 겨 다 니 며 nil 을 설정 하면 됩 니 다.
int luaext_unregisterLuaFunction(lua_State* L, int _nFuncIndex)
{
if(_nFuncIndex < 0)
{
return 0;
}
if(!lua_isfunction(L, _nFuncIndex))
{
return 0;
}
int nCount = 0;
// push key
lua_pushlightuserdata(L, GetLuaFunctionRefKey()); // stack: key
// get ref table
lua_rawget(L, LUA_REGISTRYINDEX); // stack: reftable
if (!lua_istable(L, -1))
{
return 0;
}
// push reftable index
int nStackTop = lua_gettop(L);
// push init key
lua_pushnil(L); // stack: reftable nil_key
while(lua_next(L, nStackTop))
{
// stack: reftable key value
if(lua_isfunction(L, -1))
{
// valid function
if(lua_equal(L, _nFuncIndex, -1))
{
#ifdef _DEBUG
int nTop = lua_gettop(L);
#endif
// set refFunc[key] = nil
// push key
lua_pushvalue(L, -2);
// push nil
lua_pushnil(L);
// stack: reftable key value key nil
lua_rawset(L, -5); // stack: reftable key value
#ifdef _DEBUG
assert(lua_gettop(L) == nTop);
#endif
++nCount;
}
}
// pop the value, and use the key to get the next key
lua_pop(L, 1); // stack: reftable key
}
#ifdef _DEBUG
assert(lua_gettop(L) == nStackTop);
#endif
return nCount;
}
이 일 을 해 냈 으 니 우리 가 사용 할 때 lua 가 필요 하 다.getglobal 과 유사 한 함수 입 니 다.getLua Function ByRefId 에서 push 가 호출 할 함 수 를 lua 창고 에 구현 합 니 다.
int luaext_getLuaFunctionByRefId(lua_State* L, int _nRefId)
{
#ifdef _DEBUG
int nStackTop = lua_gettop(L);
#endif
// push key
lua_pushlightuserdata(L, GetLuaFunctionRefKey()); // stack: key
// get ref table
lua_rawget(L, LUA_REGISTRYINDEX); // stack: reftable
if (!lua_istable(L, -1))
{
return 0;
}
// push key
lua_pushnumber(L, _nRefId); // stack: reftable key
// get value
lua_rawget(L, -2); // stack: reftable (value or nil)
int nRetId = 0;
if(lua_isfunction(L, -1))
{
nRetId = _nRefId;
// stack: reftable value
lua_remove(L, -2); // stack: value(func)
#ifdef _DEBUG
assert(lua_gettop(L) == nStackTop + 1);
#endif
}
else
{
// pop reftable and nil
lua_pop(L, 2);
#ifdef _DEBUG
assert(lua_gettop(L) == nStackTop);
#endif
}
return nRetId;
}
위 는 핵심 기능 의 간단 한 실현 이다.상부 에서 이 루어 지면 각자 의 생각 이 있 습 니 다. 링크 를 통 해 모든 등록 사건 의 ref 를 저장 하면 됩 니 다. 호출 할 때 모든 ref 를 호출 하면 저도 자세히 말 하지 않 겠 습 니 다.그리고 예전 에 사 용 했 던 여러 lua 를getglobal 과 등록 함수 명 방식 으로 호출 된 함 수 를 모두 재 구성 하고 또 하나의 구덩이 입 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.