2010-04-22 10 views
11

से एक lua फ़ंक्शन कॉलबैक करने के लिए मैं एक सी समारोह (ए) test_callback एक समारोह (बी) पैरामीटर और एक "के लिए कॉलबैक" होगा बीकैसे एसी समारोह

//typedef int(*data_callback_t)(int i); 
int test_callback(data_callback_t f) 
{ 
    f(3); 
} 


int datacallback(int a) 
{ 
    printf("called back %d\n",a); 
    return 0; 
} 


//example 
test_callback(datacallback); // print : called back 3 

के रूप में करने के लिए एक सूचक को स्वीकार अब है, मैं test_callback को लपेटना चाहता हूं ताकि उन्हें लुआ से बुलाया जा सके, मान लीजिए कि नाम lua_test_callback है, और इसके लिए इनपुट पैरामीटर भी लुआ फ़ंक्शन होगा। मुझे इस लक्ष्य को कैसे प्राप्त करना चाहिए?

function lua_datacallback (a) 
    print "hey , this is callback in lua" ..a 
end 


lua_test_callback(lua_datacallback) //expect to get "hey this is callback in lua 3 " 

संपादित करें:

This link बाद में उपयोग के लिए कॉलबैक फ़ंक्शन स्टोर करने के लिए एक तरह से प्रदान करते हैं।

//save function for later use 
callback_function = luaL_ref(L,LUA_REGISTRYINDEX); 


//retrive function and call it 
lua_rawgeti(L,LUA_REGISTRYINDEX,callback_function); 
//push the parameters and call it 
lua_pushnumber(L, 5); // push first argument to the function 
lua_pcall(L, 1, 0, 0); // call a function with one argument and no return values 

उत्तर

9

मुझे यकीन है कि मैं अपने प्रश्न समझ में, यदि आप पूछ रहे हैं क्या सी में lua_test_callback देखो, यह इस

int lua_test_callback(lua_State* lua) 
{ 
    if (lua_gettop(lua) == 1 && // make sure exactly one argument is passed 
     lua_isfunction(lua, -1)) // and that argument (which is on top of the stack) is a function 
    { 
     lua_pushnumber(lua, 3); // push first argument to the function 
     lua_pcall(lua, 1, 0, 0); // call a function with one argument and no return values 
    } 
    return 0; // no values are returned from this function 
} 

की तरह कुछ तुम बस लपेट नहीं कर सकते test_callback होगा चाहिए नहीं कर रहा हूँ, तो आप पूरी तरह से की जरूरत है लुआ कार्यों को कॉल करने के लिए विभिन्न कार्यान्वयन।

(संपादित करें: बदल lua_pcall को lua_call के रूप में निक ने सुझाव दिया कि मैं अभी भी किसी भी संक्षिप्तता के लिए से निपटने त्रुटि छोड़े गए।)

+2

यह lua_pcall जो सिर्फ दुर्घटनाग्रस्त बजाय ढेर पर एक त्रुटि आ जाएगी उपयोग करने के लिए बेहतर है। –

+0

अच्छा सही उदाहरण। लेकिन व्यावहारिक रूप से ऐसे lua_test_callback() फ़ंक्शंस को बार-बार लिखने के बावजूद, सामान्य, अच्छी तरह से परीक्षण किए गए इंटरफ़ेस का उपयोग करना बेहतर होता है। –

3

विभिन्न हस्ताक्षरों के साथ अलग अलग लुआ कार्यों के लिए कॉल करने का आसान तरीका:

ए मेक एक वर्ग जो लुआ राज्य को सुरक्षित रूप से बनाए रखेगी और आसान इंटरफ़ेस प्रदान करेगी। लूआ फ़ंक्शंस को स्क्रैच से कॉल न करें (बहुत सारे पुश/पॉप वर्क और आवेषण के साथ) बार-बार - बस इस क्लास इंटरफ़ेस का उपयोग करें। यह सुरक्षित, तेज़ और सुविधाजनक दृष्टिकोण है।

बी लुआ से/पर धक्का और पॉप तरीकों पुश करने के लिए/पॉप तर्क को परिभाषित ढेर:

template<typename T> void push(T argument); 
template<typename T> void get(const int index, T& return_value); 

template<> void State::push(bool arg) 
{ 
    lua_pushboolean (lua_state, arg ? 1 : 0); 
} 

template<> void State::push(float arg) 
{ 
    lua_pushnumber (lua_state, arg); 
} 

template<> void State::push(int arg) 
{ 
    lua_pushnumber (lua_state, arg); 
} 

// ... 
template<> void State::get(const int index, bool& ret) 
{ 
     if (!lua_isboolean(lua_state, index)) { ... } 
     ret = lua_toboolean(lua_state, index) != 0; 
} 

सी कार्यों को परिभाषित करें लुआ कार्यों कॉल करने के लिए:

// Call function that takes 1 argument and returns nothing 
template <typename A1> 
void call(const char * funcName, A1 arg1) 
{ 
    lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName);  // push global function f on stack 
    push (arg1);           // push first argument on stack 
    assert_call( lua_pcall(lua_state, 1, 0, this->err_h));  // call function taking 1 argument and getting no return value 
} 


// call function that takes 2 argument and returns 1 value 
template <typename R1, typename A1, typename A2> 
void callr1(const char * funcName, R1& res, A1 arg1, A2 arg2) 
{ 
    lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName);  // push global function f on stack 
    push (arg1);           // push first argument on stack 
    push (arg2); 
    assert_call( lua_pcall(lua_state, 2, 1, this->err_h));  // call function taking 2 arguments and getting 1 return value 
    get (-1, res); 
    lua_pop(lua_state, 1); 
} 

डी। सेट त्रुटि हैंडलर (lua_pcall त्रुटि के दौरान इस लुआ फ़ंक्शन को कॉल करेगा)

void setErrorHandler(const char * funcName) 
{ 
    lua_getfield (lua_state, LUA_GLOBALSINDEX, funcName); 
    this->err_h = lua_gettop(lua_state); 
} 
संबंधित मुद्दे