Discussion:
Class problem...
(too old to reply)
g***@mvwfw1.marshallwindows.com
2007-06-18 17:54:57 UTC
Permalink
I've got a class that's declared something like this:


class foo {

static int SetValue(lua_State *L);
protected:
int bal;
public:
int GetBal(void) {return bal;}
void SetBal(int value) {bal = value;}

};


int foo::SetValue(lua_State *L) {
int Param = 0;
int value = 0;
Param = luaL_checknumber(L, 2);
value = luaL_checknumber(L, 3);
lua_pushnumber(L, Param + value);
SetBal(Param + value); // <-- error point
return 1;
}


When this is compiled, it generates the following error:

"E2283 Use . or -> to call 'foo::SetBal(int)'"

How is it that a protected variable that should be accessable by members
of the same class is generating this error?

What magic am I missing in order to call the SetBal method within the
SetValue() method?

Please keep in mind that my prior "class" experience is all based around Delphi,
where this kind of thing would work.

thanks all!

g.
Chris Uzdavinis (TeamB)
2007-06-18 18:01:19 UTC
Permalink
Post by g***@mvwfw1.marshallwindows.com
class foo {
static int SetValue(lua_State *L);
int bal;
int GetBal(void) {return bal;}
void SetBal(int value) {bal = value;}
};
int foo::SetValue(lua_State *L) {
int Param = 0;
int value = 0;
Param = luaL_checknumber(L, 2);
value = luaL_checknumber(L, 3);
lua_pushnumber(L, Param + value);
SetBal(Param + value); // <-- error point
return 1;
}
"E2283 Use . or -> to call 'foo::SetBal(int)'"
How is it that a protected variable that should be accessable by members
of the same class is generating this error?
Because foo::SetValue is a static member function, it has no "this"
parameter. You cannot call non-static member functions without a
"this" parameter, unless you're explicitly calling it on an object.
Post by g***@mvwfw1.marshallwindows.com
What magic am I missing in order to call the SetBal method within the
SetValue() method?
That magic is called having an instance of foo on which you can invoke
a member function. :)

Why is SetValue a static member? I'm suspecting you don't want it to
be. If you really need it to be, then you'll have to also figure out
a way to have a foo instance on which you can call SetBal().
--
Chris (TeamB);
g***@mvwfw1.marshallwindows.com
2007-06-18 19:54:29 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
Post by g***@mvwfw1.marshallwindows.com
Param = luaL_checknumber(L, 2);
value = luaL_checknumber(L, 3);
lua_pushnumber(L, Param + value);
SetBal(Param + value); // <-- error point
return 1;
}
"E2283 Use . or -> to call 'foo::SetBal(int)'"
How is it that a protected variable that should be accessable by members
of the same class is generating this error?
Because foo::SetValue is a static member function, it has no "this"
parameter. You cannot call non-static member functions without a
"this" parameter, unless you're explicitly calling it on an object.
Ok, what exactly is a "this" parameter?
Post by Chris Uzdavinis (TeamB)
Post by g***@mvwfw1.marshallwindows.com
What magic am I missing in order to call the SetBal method within the
SetValue() method?
That magic is called having an instance of foo on which you can invoke
a member function. :)
Chris, I'm quite sure that answer is full of meaning for someone who
actually _knows_ C++. To me however, it's the equivalent of "Well ya gotta
morfle the megablum before the ixylplik transmorgraficates itself." :)

To me "having an instance of foo" is this:

foo *bar;

(or maybe foo new *bar; or foo new bar;)

I guess I don't understand why I can't call a member function within a member function.

When I try to directly access the "bal" variable within SetValue, I get an
unresolved external error and that REALLY blows my mind. How can something
defined within a class and referenced within the SAME class be called
"external"? It makes about as much sense as trying to make gym shoes out
of yogurt.
Post by Chris Uzdavinis (TeamB)
Why is SetValue a static member? I'm suspecting you don't want it to
be. If you really need it to be, then you'll have to also figure out
a way to have a foo instance on which you can call SetBal().
That was how the example I'm working with (Lua) had it set up. If I remove
the 'static' keyword from the SetValue() declaration, I get:

[C++ Error] unitMain.cpp(23): E2034 Cannot convert 'int (LuaAccount::*)(lua_State *)' to 'int (*)(lua_State *)'

in this bit of code:

const char LuaAccount::className[] = "Account";
const luaL_reg LuaAccount::methods[] = {
method(LuaAccount, deposit),
method(LuaAccount, withdraw),
method(LuaAccount, balance),
method(LuaAccount, GetValue),
method(LuaAccount, SetValue),
{0,0}
};

The 'foo' class I posted originally is a much trimmed down version of what
I'm actually working with. I just wanted to highlight the problem I was
having and not post a lot of code that wasn't relative to that problem.

tnx!

g.
g***@mvwfw1.marshallwindows.com
2007-06-18 20:49:41 UTC
Permalink
Post by g***@mvwfw1.marshallwindows.com
That was how the example I'm working with (Lua) had it set up. If I remove
[C++ Error] unitMain.cpp(23): E2034 Cannot convert 'int (LuaAccount::*)(lua_State *)' to 'int (*)(lua_State *)'
const char LuaAccount::className[] = "Account";
const luaL_reg LuaAccount::methods[] = {
method(LuaAccount, deposit),
method(LuaAccount, withdraw),
method(LuaAccount, balance),
method(LuaAccount, GetValue),
method(LuaAccount, SetValue),
{0,0}
};
I'd forgotten to include what method() is all about:

#define method(class, name) {#name, class::name}

As an experiment, I removed the static keyword from SetValue() and then
commented out the line that referenced it in the methods[] code above to
avoid the E2034 compiler error. Sure enough, it compiles without complaint.

I guess the question now would be, what's the non-static equivalent to what
the method() macro is trying to accomplish?

tnx again!

g.
Chris Uzdavinis (TeamB)
2007-06-18 21:27:25 UTC
Permalink
Post by g***@mvwfw1.marshallwindows.com
Post by Chris Uzdavinis (TeamB)
Because foo::SetValue is a static member function, it has no "this"
parameter. You cannot call non-static member functions without a
"this" parameter, unless you're explicitly calling it on an object.
Ok, what exactly is a "this" parameter?
When you call a member function on an object, there is an invisible
parameter that the compiler injects into the call so that the function
knows which object it's being called on.

If you want to conceptually look at the generated C++ code as if it
were C code, you could think of it like this:

class X
{
public:
X() : data_(0) { }
void foo(int x) { data_ += x; }
private:
int data_;
};

int main()
{
X x;
x.foo(10); // x::data_ == 10
x.foo(20); // x::data_ == 30
}

Old C++ compilers were implemented by outputting C code. Perhaps the
above code would look something like this:

struct X
{
int data_;
};

void X__initialize(X * this) { this->data_ = 0; }
void X__foo(X * this, int x) { this->data_ += x; }


int main()
{
X x;
X__initialize(&x);
X__foo(&x, 10); // x::data_ == 10
X__foo(&x, 20); // x::data_ == 30
}


The point is, the funciton X::foo() has a this parameter that the
programmer didn't write, but that was injected by the compiler. EVERY
member non-static function has such a parameter, and it holds the
address of the object it was called on. (That way a single
implementation of the function can be used with every instance of the
class.)


Static member functions do not have a this pointer passed into them
because they are not called on objects at all. They are just called,
very much like a free-standing function that is using the class as a
namespace, and that has special access to the private bases, members and
data.
Post by g***@mvwfw1.marshallwindows.com
Chris, I'm quite sure that answer is full of meaning for someone who
actually _knows_ C++. To me however, it's the equivalent of "Well ya gotta
morfle the megablum before the ixylplik transmorgraficates itself." :)
LOL. Sorry.
Post by g***@mvwfw1.marshallwindows.com
foo *bar;
(or maybe foo new *bar; or foo new bar;)
You're right, that creates an instance of an object. When you call a
member function the "this" pointer holds the address of the object you
called it on. In this case, if you created an object with a "new"
expression and then called a member on it, the "this" pointer would be
the address returned by new.
Post by g***@mvwfw1.marshallwindows.com
I guess I don't understand why I can't call a member function within a member function.
Here is (I hope) a clear example of why the static member function
cannot call a non-static member.

class Y
{
public:
Y() : data_(0) {}
void foo() { data_ += 10; }

static void g() { foo(); } // whose data_ gets updated?
private:
int data_;
};

int main()
{
Y::g(); // note: no object of type Y is involved.
}
Post by g***@mvwfw1.marshallwindows.com
When I try to directly access the "bal" variable within SetValue, I
get an unresolved external error and that REALLY blows my mind. How
can something defined within a class and referenced within the SAME
class be called "external"? It makes about as much sense as trying
to make gym shoes out of yogurt.
A static member variable is kind of like a global variable. One
exists period, with the main difference being it's contained in the
scope of the class rather than in the global namespace. Compilers
tend to treat global variables and static variables in very similar
ways. They are (or can be) created at approximately the same time,
destroyed at the same time, and have the same kind of issues
associated. Your access to them is one of the main differences, since
you have to go "through" a class to get to static members, and if
they're private (and you're not a friend, etc.) you're not allowed to
touch them.
Post by g***@mvwfw1.marshallwindows.com
Post by Chris Uzdavinis (TeamB)
Why is SetValue a static member? I'm suspecting you don't want it to
be. If you really need it to be, then you'll have to also figure out
a way to have a foo instance on which you can call SetBal().
That was how the example I'm working with (Lua) had it set up. If I remove
[C++ Error] unitMain.cpp(23): E2034 Cannot convert 'int (LuaAccount::*)(lua_State *)' to 'int (*)(lua_State *)'
Ah, I think I see. Lua is using it as a callback, and since lua is
written in C, it expects a C++ free-standing function (or static
member function) to receive the callback.

You probably will have to keep that a static member. My guess is that
the instance you're interested in seeing is identified in the
Lua_state parameter you're given. Perhaps you can keep a hash table
(or map) of object indexed by that identifier. The lua callback
receives the call, looks up the object, and then calls a member on
that object.
Post by g***@mvwfw1.marshallwindows.com
The 'foo' class I posted originally is a much trimmed down version of what
I'm actually working with. I just wanted to highlight the problem I was
having and not post a lot of code that wasn't relative to that problem.
Thanks. Appreciated!
--
Chris (TeamB);
g***@deltasoft.com
2007-06-18 23:00:07 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
Post by g***@mvwfw1.marshallwindows.com
[C++ Error] unitMain.cpp(23): E2034 Cannot convert 'int (LuaAccount::*)(lua_State *)' to 'int (*)(lua_State *)'
Ah, I think I see. Lua is using it as a callback, and since lua is
written in C, it expects a C++ free-standing function (or static
member function) to receive the callback.
You probably will have to keep that a static member. My guess is that
the instance you're interested in seeing is identified in the
Lua_state parameter you're given. Perhaps you can keep a hash table
(or map) of object indexed by that identifier. The lua callback
receives the call, looks up the object, and then calls a member on
that object.
That's pretty much what is going on. The SetValue() function is actually
called from within a Lua script. My problem is that I _must_ have some
way to communicate data to the outside world from within SetValue().

To give you a little context, the example I'm mercilessly butchering is here:
http://lua-users.org/wiki/SimpleCppBinding

I got to thinking about what you were saying and I re-examined the entire
example again. The "local" data that is actually being manipulated
is within another class. The problem is that when the program reaches the
point where I can get my hands on the data, it's gone.

I _think_ that if I move the gc_account() call to a function I have to
specifically call, I might be able to pull this off yet. Right now the
application literally exits when I call the special function I've
added to the Account class (see the example). I'm pretty sure that's
happening because the object has been disposed of.

If you've got any suggestions, I'd be happy to hear them!

Thanks again for your help!

g.
Chris Uzdavinis (TeamB)
2007-06-19 12:47:23 UTC
Permalink
Post by g***@deltasoft.com
To give you a little context, the example I'm mercilessly butchering
is here: http://lua-users.org/wiki/SimpleCppBinding
I have to apologise, but I haven't ever used Lua and don't have enough
spare time to really jump in right now.
Post by g***@deltasoft.com
I got to thinking about what you were saying and I re-examined the
entire example again. The "local" data that is actually being
manipulated is within another class. The problem is that when the
program reaches the point where I can get my hands on the data, it's
gone.
Can you elaborate on what you meay by this last sentence? Surely Lua
isn't passing you a pointer to deleted memory, so it's not clear to me
what the problem is. Maybe you need to store the data it passes to
you in your own object for later retrieval?
--
Chris (TeamB);
g***@deltasoft.com
2007-06-19 14:47:14 UTC
Permalink
Post by Chris Uzdavinis (TeamB)
Post by g***@deltasoft.com
To give you a little context, the example I'm mercilessly butchering
is here: http://lua-users.org/wiki/SimpleCppBinding
I have to apologise, but I haven't ever used Lua and don't have enough
spare time to really jump in right now.
The example is actually very short.
Post by Chris Uzdavinis (TeamB)
Post by g***@deltasoft.com
I got to thinking about what you were saying and I re-examined the
entire example again. The "local" data that is actually being
manipulated is within another class. The problem is that when the
program reaches the point where I can get my hands on the data, it's
gone.
Can you elaborate on what you meay by this last sentence? Surely Lua
isn't passing you a pointer to deleted memory, so it's not clear to me
what the problem is. Maybe you need to store the data it passes to
you in your own object for later retrieval?
One of the callbacks that is passed to Lua is a garbage collector that appears
to be called just before Lua returns. In this gc routine, the class that
was being manipulated is freed. I tried preventing the gc routine from being
called, but the program still crashes to the desktop. The drop is happening
within Lua itself, so undoubtedly I'm doing something really wrong here. :)

tnx.

g.

Loading...