2013-11-20 3 views
0

루아에 일부 클래스를 노출시키기 위해 tolua ++를 사용하는 C++ 호스트가 있습니다. 클래스 중 하나는 루아의 콜백을 등록해야하는 함수를 가지고있다. 그래서 C++ 코드가 루아 등록 함수를 호출 할 필요가있을 때 가능합니다. 그러나 함수는 테이블/클래스 함수입니다. 이전에 문자열 함수 이름 (루아 "클래스"의 일부가 아닌)을 성공으로했지만 루아 함수와 함수 이름을 어떻게 든 저장할 수 있다면 궁금합니다.C++에서 루아 콜백

내가 좋아하는 내 루아 클래스를 정의하십시오 MyClass의 내부

MyClass = {} 

function MyClass:Create() 
    local obj = {} 

    -- copy all functions from MyClass table to this local obj and return it 
    local k,v 
    for k,v in pairs(obj) do 
     obj[k] = v 
    end 

    return obj 
end 

function MyClass:Enter() 
    self.CPlusClass = CPlusClass:Create() -- this is the C++ class creation, I defined a static function Create() 
    self.CPlusClass:RegisterCallback(15, self.Callback) -- this is where I want to pass this instances function to be called back from the C++ class 
end 

function MyClass:Callback(reader) 
    -- I want to be able to use self here as well so it needs to be the same instance 
end 

: 나는 "클래스"기능 MyClass에 :: 콜백은 C에서 호출 할 수있는 루아를 등록 할 곳이다) (입력 ++ 목적. 이걸 C++ 함수에 어떻게 전달할 것입니까? C++의 Callback()이 "self"를 전달하여 클래스의 동일한 "인스턴스"가되도록 MyClass : Callback()이 호출되도록 형식이 무엇입니까?

그래서 'self'는 내가 만든 실제 변수를 말하는 것이고 변수 이름으로 전역 테이블에 있다고 가정하지만 루아 "클래스"안에있을 때 어떻게 변수 이름을 ' 자아 '도 역시 언급하고 있습니까? 만약 내가 그것을 얻을 수있는 내 C + + 함수에 전달하고 그 특정 테이블을 얻기 위해 getglobal을 호출 할 수 있도록 문자열로 저장하고 다음 또한 테이블 함수 이름을 문자열로 전달할 수 및 C++에서 수 그것을 얻고 그것을 부르십시오. 하지만 질문은, 내가 어떻게 '자체'를 실제 변수 이름으로 변환 할 수 있을까요? C에서 getglobal을 호출하여 해당 테이블을 가져올 수 있습니까?

+0

'self'는 전역 변수가 아니며, self는'table : function' 구문 설탕에 의해 정의 된 자동 변수입니다. 'function table : class (args ...) ... end'는'function table.class (self, args ...) ... end'와 동일합니다. 비슷하게'tab : class (args ...) '에 대한 호출은 tab.class (tab, args ...)와 동일하다. –

+0

그 점을 이해합니다. 그러나 자아는 내가 루아 프로그램의 어딘가에서 만든 테이블을 가리킨다. 어떤 변수 이름이 자기 자신을 가리키는 지 어떻게 알 수 있습니까? – user441521

+0

함수를 해당 테이블 "개체"에서 연결 해제하고 "개체"테이블에서 나중에 다시 사용할 수 없습니다. 콜백 함수로 클로저를 만들어 여기에서 수행하려는 작업을 수행해야합니다. –

답변

2

RegisterCallback 서명과 작업을 유지하려면 (객체 메소드 콜백을 일부 방식으로 이해하도록 향상시키는 것과 반대) 클로저를 만들어 콜백으로 전달해야합니다. 이런 식으로 뭔가 : 당신은 루아를 C++에서 CPlusClass "클래스"를 수출

function create_closure(obj, fun) 
    return function(...) 
     return obj[fun](...) 
    end 
end 

function MyClass:Enter() 
    self.CPlusClass = CPlusClass:Create() -- this is the C++ class creation, I defined a static function Create() 
    self.CPlusClass:RegisterCallback(15, create_closure(self, "Callback")) 
end 
+0

RegisterCallback()에 대한 두 번째 매개 변수는 실제로 문자열입니다. 내 원래의 희망은 자기가 참조하는 변수 이름을 가져올 수 있어야하고 "obj : Callback"과 같은 concat을 작성한 다음 C++ 함수에서 중단합니다. 이 방법을 사용하면 두 번째 매개 변수가 무엇이되어야합니까? – user441521

+0

'RegisterCallback'은 문자열을 취합니까? 그것은 나중에 이름을 바꿀 수있는 전역 함수라고 가정합니다. –

+0

필자의 생각으로는 함수가있는 테이블 이름을 조회 할 수 있었기 때문에 문자열이었습니다.이 테이블 이름은 전역이라고 가정합니다. 나는 이것을 통제하는 유일한 사람이다. 그러나 param을 변경하는 것은 큰 문제는 아니지만 closure가 리턴하는 것과 C++ 함수가 기대하는 타입을 알아야합니다. 또한, 내 C++ 프로그램은 lightuserobject의 1 매개 변수를 클로저에 전달합니다. 나는 ... 모든 매개 변수를 자동으로 처리한다고 가정합니다. – user441521

3

은 : 반드시이 C++ 클래스는 함수 또는 YourCallbackClass 인스턴스에 대한 포인터를 받아들이는 RegisterCallback이있는 가상 메소드를 사용하여 올바른 객체로 전달합니다. 그럼 당신이 필요로하는 것은 루아에 YourCallbackClass를 내보내는 것입니다 : 씬 뒤에서 루아 버전은 인스턴스를 생성하고 그것을 C++ RegisterCallback에 줄 것입니다. 예를 들어 :

class CPlusClass { 
public: 
    RegisterCallback(int val, CPlusCallback* cb) { ... store cb for later... } 
}; 

class SomeObj; // type of Objects that you want to call back into 

class CPlusCallback { 
public: 
    typedef void (SomeObj::*Method)(); 
    CPlusCallback(SomeObj* obj, Method method) { callee=obj; method=method; } 
    call() { callee->*Method(); } 
private: 
    SomeObj* callee; 
    Method method; 
}; 

귀하의 CPlusCallback은 가능성이 다른이 그냥 예입니다. 예를 들어 함수가 메서드가 아닌 함수를 원할 경우 호출 수신자를 저장할 필요가 없습니다. 둘 다 원할 경우 CPlusCallback은 기본 클래스 여야하며 call()은 가상 클래스이며 파생 클래스는 세부 정보를 적절하게 구현합니다. 귀하의 상황에 적응하십시오.

그런 다음 루아에서 할 수있는, 루아에 CPlusCallback 및 someObj에를 수출 :

somObj = SomeObj:Create() 

function MyClass:Enter() 
    -- creates Lua instance of CPlusClass, with a user data for the C++ 
    -- counterpart as member 
    self.CPlusClass = CPlusClass:Create() 
    self.CPlusCallback = CPlusCallback:Create(someObj, someObj.method) 
    self.CPlusClass:RegisterCallback(15, self.CPlusCallback) 
end 

을 위 someObj.method 당신이 클래스 someObj에 C++에서 수출하는 방법이 있다고 가정하는 경우, 적절한 서명 무효로 (SomeObj :: * 메서드)().

+0

다른 방법을 이용해 주셔서 감사합니다. 현재 나는 self를 보낸 다음 lua 클래스의 문자열 메소드 이름을 보내고 C++에서 그것을 다시 호출하는 방법을 가지고있다. 당신이 여기서했던 것과 아주 비슷합니다. 나는 그것이 어떻게 끝 났는지에 대한 세부 사항에 관심을 가졌지 만, 나는 그것을 알아 내었다. – user441521