Sign in to follow this  
Matthew Shockley

Metatable newindex Help

Recommended Posts

I have this function that a metatable calls for __newindex:
static int newindex(lua_State* L) {
	int *Ptr = (int*)lua_topointer(L, -3);
	const char *ind = lua_tostring(L, -2);
	Triangle O = GetPointerObject(Ptr); // That just returns my Triangle Object that has same memory location
	if (std::string(ind) == std::string("Name")) {
		const char *val = lua_tostring(L, -1);
		O.Name = val;
	}
	else if (std::string(ind) == std::string("className")) {
		const char *val = lua_tostring(L, -1);
		O.className = val;
	}
	return 0;
}
Only problem is... It doesn't work. Any help please?

Share this post


Link to post
Share on other sites
Quote:
Original post by Matthew Shockley
I have this function that a metatable calls for __newindex:

*** Source Snippet Removed ***

Only problem is... It doesn't work. Any help please?


Ok, as I said in another of your threads, don't use topointer in normal programming. It is for obscure runtime debugging stuff and for printing table and function values.

Oh i get it now. There is actually a function for what you are doing. lua_touserdata(L, INDEX). It returns a pointer to your object.

I don't know what you are doing with GetPointerObject, but i suspect you shouldn't be doing it. From the way it looks GetPointerObject() has an object return type, which means it is creating an object on the stack. You then go on to modify this object, which of course means nothing outside your function. This is (one of your) problem.

Furthermore, your std::string hackery there is just a roundabout way of saying strcmp() == 0. I suggest that you either use c-strings or C++ strings, don't cast between.

Assuming your object that has this metamethod is a Trangle that was allocated with lua_newuserdata(L, sizeof(Trianle)), and has a metatable called "Triangle" in the registry, your code should look like this:


/*you probly have some fancy C++ notation for class membership of a function
I don't so underscores it is*/

static int Triangle_newindex(lua_State *L) {
/*first recieve and check args*/
Triangle *myobj = luaL_checkudata(L, 1, "Triangle"); /*note that it is a pointer*/
const char *key = luaL_checkstring(L, 2); /*you should use positive indicies for args*/
const char *val = luaL_checkstring(L, 3);
/*do the actual thinking*/
/*if this got any bigger, I would use luaL_checkopt and switch*/
if (strcmp(key, "Name") == 0)
myobj->Name = val; /*note pointer deref*/
else if (strcmp(key, "className") == 0)
myobj->className = val;
return 0;
}



That should work (not tested). You shoudl set up your allocation and metatabling to work like this.

Also a pet peeve, please don't Capitalize Every Identifier, It Makes It Hard To Type.

Share this post


Link to post
Share on other sites
Sorry, I got in the habit of capitalizing important stuff that I might need to use later or don't understand absolutely. The GetPointerObject(int *Ptr) function is one I made that just goes through the list of all my Triangle Objects to see if it's Triangle::Pointer is equal to Ptr, then returns the corresponding one. Look, this is the problem with what you are doing, each time the user calls my "Object" function, it creates a new Triangle object and adds it to the list; there will be an undefined number of Triangles created so I can't give each one a individual name. That's why I was using lua_topointer so each one would have it's own specific ID. If there is another way to do this without creating specific name for each object, please tell me.

Share this post


Link to post
Share on other sites
Ok, I have this and it works, but I still don't see how when I create the userdata and the Triangle, and add the triangle to the vector, when I get to the index function, it can find the same triangle from the vector. Here is what I have:

static int index(lua_State* L) {
Triangle *myobj = luaL_checkudata(L, 1, "Triangle");
lua_pushstring(L, "Please work!");
return 1;
}

static int Object(lua_State* L) {
const char *val = lua_tostring(L, -1);
lua_newuserdata(L, 0);
int uTop = lua_gettop(L);
luaL_newmetatable(L, "Triangle");
lua_setmetatable(L, -2);
lua_getmetatable(L, -1);
int Top = lua_gettop(L);
lua_pushliteral(L, "__index");
lua_pushcfunction(L, index);
lua_settable(L, Top);
lua_pushvalue(L, uTop);
// Add triangle to vector here but don't know to connect triangle to userdata
return 1;
}


Ahh, this is driving me crazy! I don't know how to explain what I am saying. I want it so that the user creates a userdata with Object(), it adds a Triangle to my vector and whenever the index function is called, I need to find out what Triangle in the vector corresponds to the userdata in the index function and change it's member variable's value. Do you understand?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this