2011-01-21 16 views
6

में वापस कॉल करें मैंने एक बार सोचा है कि मैं लुआ में एक क्लास विधि को ओवरराइड कर सकता हूं ताकि जब मैं उस समारोह को सी ++ में कॉल करूँ, तो यह लुआ में ओवरराइड होगा। मेरा मतलब है, इस तरह:लुआ में सी ++ विधि को ओवरराइड करना और इसे सी ++

सी ++ वर्ग


class Person { 
public: 
    Person(); // ctr 
    virtual void shout(); // Meant to be overriden 
}; 

मान लें मुझे लगता है कि वर्ग lua से आबद्ध ताकि lua में, मैं वस्तु का उपयोग कर सकते है:


--Lua code 
p = Person:new() 
p:shout() 

क्या मैं मैं प्राप्त करने की कोशिश कर रहा हूं:

लुआ फ़ाइल


--luafile.lua 
p = Person:new() --instantiate 

--override shout() 
p.shout = function(self) print("OVERRIDEN!") end 

सी ++ कोड


int main() { 
    lua_State* l = lua_open(); 
    luaL_loadlibs(l); 
    bind_person_class(l); 

    luaL_dofile("luafile.lua"); 
    Person* p = (Person*) get_userdata_in_global(l, "p"); // get the created person in lua 
    p->shout(); // expecting "OVERRIDEN" to be printed on screen 

    lua_close(l); 
    return 0; 
} 

उपरोक्त कोड में, आप देख सकते हैं कि मैं lua में व्यक्ति की विधि को ओवरराइड और उम्मीद ओवरराइड विधि C++ के नाम से जाना करने के लिए कोशिश कर रहा हूँ। हालांकि, जब मैं इसे आज़माता हूं, ओवरड्रीन विधि निष्पादित नहीं होती है। मैं जो हासिल करने की कोशिश कर रहा हूं वह है कि ओवरसीन विधि सी ++ में निष्पादित की जाती है। आप इसे कैसे प्राप्त करते हैं?

===================

मैं इस लक्ष्य को हासिल करने के लिए एक तरह से सोचा है, लेकिन मुझे यकीन है कि अगर यह अच्छा है नहीं कर रहा हूँ। मेरा विचार है कि निर्यातित वर्ग में लूआ में वैश्विक चर नाम का प्रतिनिधित्व करने वाली एक स्ट्रिंग होनी चाहिए जिसका उपयोग इस वर्ग के उदाहरण को पकड़ने के लिए किया जाता है। इस तरह:


class Person { 
public: 
    Person(); 
    string luaVarName; // lua's global variable to hold this class 
    virtual void shout() { 
    luaL_dostring(luaVarName + ":shoutScript()"); // now shout will call shoutScript() in lua 
    } 
}; 

तो, lua में, वस्तु shoutScript() को लागू करने और वैश्विक वर आवंटित करने के लिए जिम्मेदार आपत्ति करने के लिए है:


--LUA 
p = Person:new() 
p.shoutScript = function(self) print("OVERRIDEN") end 
p.luaVarName = "p" 
ऊपर कोड के साथ

, मैं प्राप्त कर सकते हैं जो मैं चाहता (हेवन हालांकि, इसका परीक्षण नहीं किया गया)। लेकिन, क्या मैं चाहता हूं कि हासिल करने के लिए कोई अन्य, उचित तरीका है?

+0

क्या आप समझते हैं कि पहला बदलाव क्यों विफल रहता है? – GManNickG

+0

@GMan: मुझे लगता है क्योंकि मैंने वास्तव में विधि को ओवरराइड नहीं किया है। AFAIK, जब आप C++ में विधियों (या फ़ंक्शंस) को कॉल करते हैं, तो आप उस पते का जिक्र कर रहे हैं जहां निर्देश स्थित है। और जब कोई फ़ंक्शन ओवरराइड होता है तो किसी अन्य पते को संदर्भित करने के लिए तंत्र होता है। तो जब मैं इसे LUA में "ओवरराइड" करता हूं, तो C++ इसके बारे में नहीं जानता है, ताकि वास्तविक कार्य को बुलाया जा सके। CMIIW। – Radi

उत्तर

3

हमने क्यूटी से लुआ के स्वचालित बाध्यकारी lqt में क्या किया है, यह है कि प्रत्येक वर्ग जिसे हम बांधते हैं, जिसके लिए वर्चुअल विधियां हैं, हम एक प्रॉक्सी "खोल" वर्ग बनाते हैं, जो स्वयं को लुआ राज्य में पंजीकृत करता है।

अपने (सरलीकृत) वर्ग के लिए

तो:

class lqt_shell_Person : public Person { 
    lua_State *L; 
public: 
    lqt_shell_Person(lua_State *L); // registers itself into the Lua state 
    virtual void shout(); 
}; 

हम userdata का उपयोग कर लुआ में इन वस्तुओं का प्रतिनिधित्व करते हैं:

class Person { 
public: 
    virtual void shout(); // Meant to be overriden 
}; 

हम निम्नलिखित वर्ग उत्पन्न करते हैं।प्रत्येक की अपनी पर्यावरण तालिका होती है, जिसमें हम __newindex और __index मेटामाइड्स (__index फ़ंक्शन पर्यावरण में दिखते हैं और फिर कक्षा तालिका में) इंगित करते हैं। इसका उपयोग करके, उपयोगकर्ता वस्तुओं पर कस्टम फ़ील्ड स्टोर कर सकता है। उन्होंने यह भी इस तरह आभासी काम करता है, को लागू कर सकते हैं:

p = Person.new() 
function p:shout() print("Hello world!") end 

हमारे lqt_shell_Person::shout विधि में, हम पहली बहस लाने, और फिर जाँच userdata के वातावरण तालिका में एक समारोह shout है कि क्या वहाँ। यदि वहां है, तो हम इसे तर्क के साथ बुलाते हैं। यदि कोई नहीं है, तो हम मूल कार्य को कॉल करते हैं। अमूर्त तरीकों के मामले में, हम एक लुआ त्रुटि फेंक देते हैं।

आशा है कि आपको यह उपयोगी लगेगा।

+0

@ माइकल: धन्यवाद। यह एक बहुत अच्छा समाधान है :) ठीक वही है जो मैं ढूंढ रहा हूं। – Radi

2

लुआ "वैचारिक रूप से" सी ++ से अलग है। लुआ prototype-based OO भाषा है। सी ++ कक्षा आधारित ओओ भाषा है। लुआ ऑब्जेक्ट इंटरफ़ेस रन-टाइम को संशोधित कर सकता है, ऑब्जेक्ट के निर्माण के बाद ऑब्जेक्ट प्रकार को संशोधित नहीं कर सकता है।

तो आप अपने लुआ ऑब्जेक्ट इंटरफ़ेस के साथ कभी भी क्या करते हैं, परिवर्तन सी ++ प्रोग्राम पर वापस प्रतिबिंबित नहीं होते हैं बल्कि लुआ में रहते हैं।

+1

धन्यवाद। यह मेरे लिए चीजों को स्पष्ट बनाता है। हालांकि, मैं वास्तव में वर्णित चीजों को प्राप्त करने के लिए अन्य (अधिक सुरुचिपूर्ण) तरीका जानना चाहता हूं। या शायद मुझे और सामान्य बात पूछनी चाहिए: लुआ में ऑब्जेक्ट-लेवल (सी ++ में) पर बदलाव को लागू करने का सही तरीका क्या है? – Radi

संबंधित मुद्दे