2013-08-15 4 views
8

से सी ++ वस्तु सूचक को निकालने के लिए मैं सी में एक वर्ग ++ "प्वाइंट" कहा जाता है:कैसे लुआ

class Point 
{ 
public: 
    int x, y; 

    //constructor 
    Point(int x, int y) 
    { 
    this->x = x; 
    this->y = y; 
    } 
}; 

मेरा लक्ष्य के लिए एक लुआ स्क्रिप्ट के साथ एक प्वाइंट वस्तु का दृष्टांत के लिए, और निकालने के सूचक सक्षम होने के लिए है लुआ स्टैक से यह वस्तु।

यहां मेरा (वर्तमान में काम नहीं कर रहा है) प्रयास है जो उम्मीद करता है कि मैं वास्तव में क्या करने की कोशिश कर रहा हूं; ध्यान दें कि इस कोड को अनिवार्य रूप से this tutorial से कॉपी/पेस्ट संशोधित किया गया है और यह है कि मैं लुआ 5.2 उपयोग कर रहा हूँ:

static int newPoint(lua_State *L) 
{ 
    int n = lua_gettop(L); 
    if (n != 2) 
     return luaL_error(L, "expected 2 args for Point.new()", n); 

    // Allocate memory for a pointer to object 
    Point **p = (Point **)lua_newuserdata(L, sizeof(Point *)); 

    double x = luaL_checknumber (L, 1);  
    double y = luaL_checknumber (L, 2); 

    //I want to access this pointer in C++ outside this function 
    *p = new Point(x, y); 

    luaL_getmetatable(L, "Point"); // Use global table 'Point' as metatable 
    lua_setmetatable(L, -2); 

    return 1; 
} 

static const luaL_Reg pointFuncs[] = { 
    {"new", newPoint}, 
    {NULL, NULL} 
}; 

//register Point to Lua 
void registerPoint(lua_State *L) 
{ 
    lua_createtable(L, 0, 0); 
    // Register metatable for user data in registry 
    luaL_newmetatable(L, "Point"); 
    luaL_setfuncs(L, pointFuncs, 0);   
    lua_pushvalue(L,-1); 
    lua_setfield(L,-2, "__index"); 
    lua_setglobal(L, "Point"); 
} 

Point* checkPoint(lua_State* L, int index) 
{ 
    void* ud = 0; 
    luaL_checktype(L, index, LUA_TTABLE); 
    lua_getfield(L, index, "__index"); 
    ud = luaL_checkudata(L, index, "Point");; 

    return *((Point**)ud);  
} 

int main() 
{ 
    lua_State *L = luaL_newstate(); 
    luaL_openlibs(L); 
     registerPoint(L); 
    luaL_dofile(L, "testz.lua"); 
    lua_getglobal(L, "Point"); 
    Point *foo = checkPoint(L, lua_gettop(L)); 
     std::cout << "x: " << foo->x << " y: " << foo->y; 
    lua_close(L); 
    return 0; 
} 

और यहाँ लुआ स्क्रिप्ट है:

local point = Point.new(10,20) 

इस कोड चल रहा है, मैं निम्नलिखित त्रुटि मिलती है : "खराब तर्क # 3 (प्वाइंट अपेक्षित, टेबल मिला)" लाइन पर: ud = luaL_checkudata (एल, इंडेक्स, "प्वाइंट") चेकपॉइंट() फ़ंक्शन के अंदर।

यदि कोई मुझे सही दिशा में चला सकता है, तो इसकी सराहना की जाएगी।

उत्तर

8

आपके उपरोक्त उपयोग और बाध्यकारी में कुछ समस्याएं हैं।

अपनी परीक्षण स्क्रिप्ट के अंदर, local point आपके होस्ट C++ प्रोग्राम द्वारा नहीं देखा जाएगा। ऐसा इसलिए है क्योंकि, ठीक है, यह उस स्क्रिप्ट के लिए स्थानीय है। यदि आप इसे सी ++ से एक्सेस करना चाहते हैं, तो स्क्रिप्ट से मूल्य के रूप में point वापस करें या इसे वैश्विक बनाएं और इसे lua_getglobal(L, "point") का उपयोग करके पुनर्प्राप्त करें।

checkPoint फ़ंक्शन में कुछ अनावश्यक कोड है। यदि आप लुआ सी एपीआई द्वारा प्रदान किए गए अन्य luaL_check* फ़ंक्शंस को देखते हैं, तो वे मुख्य रूप से जांचते हैं कि स्टैक इंडेक्स पर दिया गया मान सही प्रकार है या नहीं। यदि यह उस प्रकार को उस पर परिवर्तित करता है तो कुछ C++ उपयोग कर सकते हैं।

तो अपने 'चौकी' समारोह में सभी तुम सच में क्या करने की जरूरत है:

Point* checkPoint(lua_State* L, int index) 
{ 
    return *((Point **) luaL_checkudata(L, index, "Point")); 
} 

आप उदाहरण के लिए, यह करने के लिए अपनी स्क्रिप्ट को बदलते हैं:

local point = Point.new(10,20) 
return point 

आप का उपयोग करने में सक्षम होना चाहिए point सी ++ से निम्नलिखित तरीके से:

// ... 
luaL_dofile(L, "testz.lua"); 

Point *foo = checkPoint(L, -1); 
std::cout << "x: " << foo->x << " y: " << foo->y; 
// ... 

एक अन्य महत्वपूर्ण बिंदु regardin है lua के संपर्क में आने पर जी सी ++ ऑब्जेक्ट आजीवन। चूंकि आप सी ++ 'नए' ऑपरेटर के साथ आवंटित और निर्माण कर रहे हैं जब भी Point.new स्क्रिप्ट से कहा जाता है, तो आप अप्रत्यक्ष रूप से कह रहे हैं कि लुआ इस खुला सी ++ ऑब्जेक्ट के जीवनकाल को संभालने दें। इसका मतलब है कि आप 'अंतिमकरण' या गैर-निर्धारिती विनाशक के रूप में कार्य करने के लिए __gc मेटामाउड को भी कार्यान्वित करना चाहते हैं। इसके बिना आपको point ऑब्जेक्ट को 'डिलीट' करने का कोई तरीका नहीं होगा और जब लुआ कचरा संबंधित उपयोगकर्ता डेटा एकत्र करेगा तो स्पेस पुनः प्राप्त करें।

ऐसा करने के लिए इस प्रकार आप अपने कोड को बढ़ाने कर सकते हैं:

  • एक deletePoint समारोह userdata जीसी पर lua से बुलाया जाता है कि लिखें।

    static int deletePoint(lua_State *L) 
    { 
        Pointer **p = checkPoint(L, 1); 
        delete *p; 
        *p = NULL; // probably not needed but to be safe 
        return 0; 
    } 
    
  • अपने pointFuncs तो lua इसके बारे में पता करने के लिए कि जोड़ें।

    static const luaL_Reg pointFuncs[] = 
    { 
        {"new", newPoint}, 
        {"__gc", deletePoint}, 
        {NULL, NULL} 
    }; 
    
+1

समझाया जो मुझे पता होना चाहिए! 1000x धन्यवाद श्रीमान। – user2687268

+0

@ user2687268 मैंने उपयोगकर्ता डेटा को साफ करने के बारे में एक नोट जोड़ा है। – greatwolf

+0

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

5

मैं अपनी खुद की बाध्यकारी नहीं लिख सलाह देते हैं, बल्कि एक परीक्षण किया है और एक दस्तावेज का उपयोग करें, इस तरह के रूप luabridge या luabind

आपका बंधन को कम किया जा जाएगा:

getGlobalNamespace (L) 
    .beginClass<Point>("Point") 
    .addConstructor<void (*) (int,int)>() 
    .addData("X", &Point::x) 
    .addData("Y", &Point::y) 
    .endClass() 
; 

और अपने lua होगा

local point = Point(10,20) 

लुब्रिज के साथ देखो।

मूल्य निकालने के लिए, उदाहरण के लिए देखें LuaRef in luabridge। यदि आप सी ++ 11 का उपयोग करते हैं तो कुछ अन्य सुंदर लुआ बाध्यकारी पुस्तकालय हैं।

+1

मैं निश्चित रूप से luabind बाहर की जाँच करेगा। एक सीखने का अनुभव के रूप में मैं हालांकि यह काम करना चाहता हूं। दुर्भाग्यवश, मुझे अपने लूआ कोड में कोलन ऑपरेटर पर स्विच करने के बाद भी पहले भी वही त्रुटि मिलती है और तर्क को नएपॉइंट() फ़ंक्शन में बदल दिया जाता है। क्या आपको पता चलेगा कि यह क्यों है? – user2687268

+0

ने मेरा जवाब अपडेट किया क्योंकि आईडी में वास्तविक स्पष्टीकरण नहीं था, और महान भेड़िये ने –