2012-04-25 9 views
6

मैं लुआ 5.1 के साथ रयान पावलिक के मास्टर वितरण से लुइबिंड 0.9.1 का उपयोग कर रहा हूं, विन XP SP3 + नवीनतम पैच x86 पर सिग्विन, 1.48, जीसीसी बढ़ाएं 4.3.4। लुआ और बूस्ट साइगविन प्री-संकलित संस्करण हैं।luabind: गैर-निर्मित कक्षाओं द्वारा अनुक्रमित तालिका से मूल्यों को पुनर्प्राप्त नहीं किया जा सकता

मैंने सफलतापूर्वक दोनों स्थिर और साझा संस्करणों में लुभाइंड बनाया है।

दोनों संस्करण test_object_identity.cpp परीक्षण के लिए सभी परीक्षणों को पार करते हैं जो दोनों संस्करणों में विफल रहता है।

मैंने निम्न समस्या को हल किया है: यदि किसी तालिका में कोई प्रविष्टि गैर अंतर्निर्मित कक्षा (यानी, int, string, आदि नहीं) के लिए बनाई गई है, तो मान पुनर्प्राप्त नहीं किया जा सकता है।

यहाँ एक कोड टुकड़ा है कि इस दर्शाता है:

#include "test.hpp" 
#include <luabind/luabind.hpp> 
#include <luabind/detail/debug.hpp> 

using namespace luabind; 

struct test_param 
{ 
    int obj; 
}; 

void test_main(lua_State* L) 
{ 
    using namespace luabind; 

    module(L) 
    [ 
     class_<test_param>("test_param") 
      .def_readwrite("obj", &test_param::obj) 
    ]; 

    test_param temp_object; 
    object tabc = newtable(L); 
    tabc[1] = 10; 
    tabc[temp_object] = 30; 

    TEST_CHECK(tabc[1] == 10);    // passes 
    TEST_CHECK(tabc[temp_object] == 30); // FAILS!!! 

} 

tabc [1] वास्तव में 10 है, जबकि tabc [temp_object] 30 नहीं है! (वास्तव में, यह शून्य लगता है)

हालांकि, अगर मैं टैबक प्रविष्टियों पर जाने के लिए पुनरावृत्ति का उपयोग करता हूं, तो कॉररेक्ट कुंजी/मूल्य जोड़े के साथ दो प्रविष्टियां हैं।

कोई विचार?

Btw, इस तरह == ऑपरेटर ओवरलोडिंग:

#include <luabind/operator.hpp> 

struct test_param 
{ 
    int obj; 
    bool operator==(test_param const& rhs) const 
    { 
     return obj == rhs.obj; 
    } 
}; 

और

module(L) 
    [ 
     class_<test_param>("test_param") 
      .def_readwrite("obj", &test_param::obj) 
      .def(const_self == const_self) 
    ]; 

परिणाम को बदल नहीं करता है।

मैंने [] ऑपरेटर से settable() और gettable() पर स्विच करने का भी प्रयास किया। नतीजा वही है। मैं डीबगर के साथ देख सकता हूं कि कुंजी का डिफ़ॉल्ट रूपांतरण लागू होता है, इसलिए मुझे लगता है कि त्रुटि कहीं से उत्पन्न होती है, लेकिन यह पता लगाने के लिए कि वास्तव में समस्या क्या है।

struct test_param : wrap_base 
{ 
    int obj; 
    bool operator==(test_param const& rhs) const 
    { return obj == rhs.obj ; } 
}; 

void test_main(lua_State* L) 
{ 
    using namespace luabind; 
    module(L) 
    [ 
     class_<test_param>("test_param") 
       .def(constructor<>()) 
       .def_readwrite("obj", &test_param::obj) 
       .def(const_self == const_self) 
    ]; 

    object tabc, zzk, zzv; 
    test_param tp, tp1; 
    tp.obj = 123456; 
    // create new table 
    tabc = newtable(L); 
    // set tabc[tp] = 5; 
    //   o  k v 
    settable(tabc, tp, 5); 
    // get access to entry through iterator() API 
    iterator zzi(tabc); 
    // get the key object 
    zzk = zzi.key(); 
    // read back the value through gettable() API 
    //    o  k 
    zzv = gettable(tabc, zzk); 
    // check the entry has the same value 
    // irrespective of access method 
    TEST_CHECK (*zzi == 5 && 
       object_cast<int>(zzv) == 5); 
    // convert key to its REAL type (test_param) 
    tp1 = object_cast<test_param>(zzk); 
    // check two keys are the same 
    TEST_CHECK(tp == tp1); 
    // read the value back from table using REAL key type 
    zzv = gettable(tabc, tp1); 
    // check the value 
    TEST_CHECK(object_cast<int>(zzv) == 5); 
    // the previous call FAILS with 
    // Terminated with exception: "unable to make cast" 
    // this is because gettable() doesn't return 
    // a TRUE value, but nil instead 
} 

उम्मीद है, किसी को होशियार से मुझे यह पता लगा सकते हैं, Thx

मैं:

निम्नलिखित सरल परीक्षण का मामला शो के रूप में, वहाँ निश्चित रूप से जटिल प्रकार के लिए Luabind के रूपांतरण में एक बग कर रहे हैं इस तथ्य को हल कर लिया है कि लुबाइंड एक नई डिस्टिंट ऑब्जेक्ट बनाता है हर बार जब आप जटिल मान का उपयोग कुंजी के रूप में करते हैं (लेकिन यदि आप आदिम एक या ऑब्जेक्ट का उपयोग नहीं करते हैं)।

struct test_param : wrap_base 
{ 
    int obj; 
    bool operator==(test_param const& rhs) const 
    { return obj == rhs.obj ; } 
}; 

void test_main(lua_State* L) 
{ 
    using namespace luabind; 

    module(L) 
    [ 
     class_<test_param>("test_param") 
      .def(constructor<>()) 
      .def_readwrite("obj", &test_param::obj) 
      .def(const_self == const_self) 
    ]; 

    object tabc, zzk, zzv; 
    test_param tp; 
    tp.obj = 123456; 
    tabc = newtable(L); 
    //   o  k v 
    settable(tabc, tp, 5); 
    iterator zzi(tabc), end; 
    std::cerr << "value = " << *zzi << "\n"; 
    zzk = zzi.key(); 
    //   o  k v 
    settable(tabc, tp, 6); 
    settable(tabc, zzk, 7); 
    for (zzi = iterator(tabc); zzi != end; ++zzi) 
    { 
     std::cerr << "value = " << *zzi << "\n"; 
    } 
} 

सूचना कैसे tabc [tp] पहला मान 5 है और फिर जब कुंजी वस्तु के माध्यम से पहुँचा 7 के साथ ओवरराइट है:

यहां एक छोटा परीक्षण का मामला है कि इस दर्शाता है। हालांकि, जब टीपी के माध्यम से फिर से पहुंचाया जाता है, तो एक नई प्रविष्टि बन जाती है। यही कारण है कि gettable() बाद में विफल रहता है।

Thx, डेविड

+0

क्या आपने कभी इस मुद्दे को हल किया है? टेबल के लिए कुंजी के रूप में int मानों का उपयोग करते समय मुझे पहले से ही यह समस्या है। स्थानीय परीक्षणटेबल = {[10] = "हरा", [9] = "नारंगी", [8] = "पीला"} - अगर मैं संख्याओं की बजाय तारों के बजाय स्ट्रिंग का उपयोग करता हूं - यह ठीक काम करता है - मैं इस तालिका को एक परम के रूप में देता हूं एक सी ++ फ़ंक्शन के लिए और मुझे भी कास्ट त्रुटि मिलती है – Steve

उत्तर

0

अस्वीकरण: मैं luabind पर एक विशेषज्ञ नहीं हूँ। यह पूरी तरह से संभव है कि मुझे लुइबिंद की क्षमताओं के बारे में कुछ याद आया है।

सबसे पहले, test_param को लुआ कुंजी में परिवर्तित करते समय लुबाइंड क्या कर रहा है? डिफ़ॉल्ट नीति प्रतिलिपि है। लुबाइंड दस्तावेज़ीकरण को उद्धृत करने के लिए:

यह पैरामीटर की एक प्रति बना देगा। मानकों को मानते समय यह डिफ़ॉल्ट व्यवहार है। ध्यान दें कि इसका उपयोग केवल C++ से Lua तक जाने पर किया जा सकता है। इस नीति के लिए आवश्यक है कि पैरामीटर प्रकार में एक सुलभ प्रतिलिपि है।

अभ्यास में, इसका यह मतलब है कि luabind एक नई वस्तु है (जिसे "पूर्ण userdata") जो लुआ कचरा कलेक्टर के स्वामित्व में है पैदा करेगा और इसे में अपने struct कॉपी जाएगा। यह करने के लिए एक बहुत ही सुरक्षित चीज है क्योंकि यह अब सी ++ ऑब्जेक्ट के साथ आप जो करते हैं उससे कोई फर्क नहीं पड़ता; लुआ ऑब्जेक्ट वास्तव में बिना किसी ओवरहेड के चारों ओर चिपकेगा। वस्तुओं के मूल्य-प्रकार के लिए बाइंडिंग करने का यह एक अच्छा तरीका है।

लुआइंड हर बार जब आप इसे लुआ पास करते हैं तो एक नई वस्तु क्यों बनाते हैं? अच्छा, यह और क्या कर सकता है? इससे कोई फर्क नहीं पड़ता कि पास ऑब्जेक्ट का पता वही है, क्योंकि मूल सी ++ ऑब्जेक्ट बदल गया था या नष्ट हो गया था क्योंकि इसे पहले लुआ में पारित किया गया था। (याद रखें, इसे प्रतिलिपि द्वारा मूल्य के अनुसार प्रतिलिपि में कॉपी किया गया था।) इसलिए, केवल == के साथ, लुबाइंड को उस प्रकार की प्रत्येक वस्तु की एक सूची बनाए रखना होगा जिसे कभी लुआ (संभवतः कमजोर) में पारित किया गया था और आपकी तुलना करें यह देखने के लिए कि क्या यह मेल खाता है, प्रत्येक के खिलाफ ऑब्जेक्ट करें। लुबिंद ऐसा नहीं करता है (न ही मुझे लगता है कि यह चाहिए)।

अब, लूआ पक्ष को देखें। हालांकि लुबिंद दो अलग-अलग वस्तुओं को बनाता है, फिर भी वे बराबर हैं, है ना? खैर, पहली समस्या यह है कि, कुछ अंतर्निर्मित प्रकारों के अलावा, लुआ केवल संदर्भ द्वारा वस्तुओं को पकड़ सकता है। उन "पूर्ण उपयोगकर्ता डेटा" में से प्रत्येक जो मैंने पहले उल्लेख किया है वह वास्तव में एक सूचक है। इसका मतलब है कि वे समान नहीं हैं।

लेकिन वे बराबर हैं, अगर हम __eq मेटा ऑपरेशन को परिभाषित करते हैं। दुर्भाग्य से, लुआ खुद ही इस मामले का समर्थन नहीं करता है। तालिका कुंजी के रूप में उपयोग किए जाने पर Userdata हमेशा पहचान से तुलना की जाती है, इससे कोई फर्क नहीं पड़ता। यह वास्तव में उपयोगकर्ता डेटा के लिए विशेष नहीं है; यह टेबल के लिए भी सच है। (ध्यान दें कि इस मामले का सही ढंग से समर्थन करने के लिए, लुआ को __eq के अलावा ऑब्जेक्ट पर हैशकोड ऑपरेशन को ओवरराइड करने की आवश्यकता होगी। लुआ भी हैशकोड ऑपरेशन को ओवरराइड करने का समर्थन नहीं करता है।) मैं लुआ के लेखकों के लिए बात नहीं कर सकता क्यों उन्होंने नहीं किया इसे अनुमति दें (और इससे पहले सुझाव दिया गया है), लेकिन वहां है।

तो, विकल्प क्या हैं?

  • सरल बात एक बार (स्पष्ट) एक वस्तु को test_param कनवर्ट करते हैं, और फिर मेज सूचकांक करने के लिए उस वस्तु का उपयोग दोनों बार होगा। हालांकि, मुझे संदेह है कि यह आपके खिलौने के उदाहरण को ठीक करता है, यह अभ्यास में बहुत उपयोगी नहीं है।
  • एक और विकल्प बस कुंजी के रूप में उपयोग करने के लिए नहीं है। असल में, मुझे लगता है कि यह एक बहुत अच्छा सुझाव है, क्योंकि इस तरह के हल्के वजन बाध्यकारी काफी उपयोगी है, और एकमात्र अन्य विकल्प इसे त्यागना है।
  • ऐसा लगता है कि आप अपने प्रकार पर एक कस्टम रूपांतरण परिभाषित कर सकते हैं। आपके उदाहरण में, आपके प्रकार को लुआ संख्या में परिवर्तित करना उचित हो सकता है जो तालिका सूचकांक के रूप में अच्छी तरह से व्यवहार करेगा।
  • एक अलग प्रकार के बाध्यकारी का उपयोग करें। कुछ उपरांत होगा, लेकिन यदि आप पहचान चाहते हैं, तो आपको इसके साथ रहना होगा। ऐसा लगता है luabind तरह रैपर, जो आप पहचान को सुरक्षित रखने के लिए उपयोग करने के लिए आवश्यकता हो सकती है के लिए कुछ समर्थन हासिल है:

    एक आवरण के साथ एक सूचक या एक पंजीकृत वर्ग के संदर्भ में लुआ को पारित कर दिया जाता है, तो luabind इसके लिए क्वेरी करेगा गतिशील प्रकार है । यदि गतिशील प्रकार wrap_base से प्राप्त होता है, तो ऑब्जेक्ट पहचान संरक्षित होती है।

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