This has been driving me nuts for over a week. Below are two snippets of Lua code from a robot player in the game Bitfighter (written in C++, using a variant of LuaWrapper for binding).
When I first start the Lua script, both work exactly as expected. But after some minutes of intense object creation and destruction, variant 2 stops working, and gives me the following error:
robot.lua:253: attempt to call missing or unknown method 'getEnergy' (a nil value)
To my eyes these should function identically. Who can explain the difference?
Notes: target is a (heavy) userdata representing a C++ object. getEnergy and getHealth are properly registered C++ functions. I can reproduce this differing behavior easily. This is Lua 5.1, using the luavec mod.
Variant 1 - always works
local mt = getmetatable(target)
local pow = mt.getEnergy(target) + mt.getHealth(target)
Variant 2 - starts failing after script has been running for an arbitrary amount of time
local pow = target:getEnergy() + target:getHealth()
To track what happens when it stops working you can wrap the call in pcall and explore what happened with the target value:
local ok, res = pcall(function() return target:getEnergy() + target:getHealth() end)
if not ok then
local s = "Invalid target value: "..tostring(target).." "..type(target).."\n"
for k, v in pairs(target) do s = s.."target "..tostring(k).." "..tostring(v).."\n" end
for k, v in pairs(getmetatable(target)) do s = s.."meta "..tostring(k).." "..tostring(v).."\n" end
-- add anything else that helps you figure out what happened to target
error(res..s)
end
local pow = res
I strongly suspect the issue is that you have a class or struct similar to this:
struct Foo
{
Bar bar;
// Other fields follow
}
And that you've exposed both Foo and Bar to Lua via LuaWrapper. The important bit here is that bar is the first field on your Foo struct. Alternatively, you may have some class that inherits from some other base class and both the derived and base class are exposed to LuaWrapper.
LuaWrapper uses an function called an Identifier to uniquely track each object (like whether or not the given object has already been added to the Lua state). By default it uses the object address as a key. In cases like the one posed above it is possible that both Foo and Bar have the same address in memory, and thus LuaWrapper can get confused.
This may result in grabbing the wrong object's metatable when attempting to look up a method. Clearly, since it's looking at the wrong metatable it won't find the method you want, and so it will appear as if your metatable has mysteriously lost entries.
I've checked in a change that tracks each object's data per-type rather than in one giant pile. If you update your copy LuaWrapper to latest one from the repository I'm fairly certain your problem will be fixed.
When you say it stops working at some stage, but works fine before... Could it be that you overwrite the .getEnergy function anywhere at runtime?
Maybe you're running a foo.getEnergy = nil instead of a foo.getEnergy == nil somewhere? Sounds like it might be a late initialization gone awry :)
Related
Debugging some code with Visual Studio and I was surprised to find that the values of the property of an object looked great before the call into a method and then were corrupted as soon as I entered the method:
The call comes from here. The debugger reports that thingA.property = 0.14
method1()
{
Thing thingA;
object.method2(thingA)
}
and goes into here and the debugger reports thingMine.property = 4.0E-315#DEN
method2(Thing thingMine)
{
....
}
When I change scope back up to method1 the property looks fine and scoping back down to method2 the property takes on a wildly different value.
What can cause the value to change? Back in the old days with C, I can mangle memory by fooling around with pointers. However, there's nothing fancy about this code. There are no (explicit) pointers. The compiler is happy with the cast / class of all the objects. There is no fancy inheritance or overloading.
To add more detail, Thing is not simply a class with properties and methods. Its properties are objects, but still not very fancy:
class Thing {
public:
AnotherThing thingInsideAThing;
...
}
It is the property of AnotherThing that is getting mangled.
My understand of pass-by-value is based upon my ancient schooling in C. I thought calling a method would push an explicit copy of thingA onto the stack. Does it push a bad address for thingA.object onto the stack? I thought pass-by-value was always the safest way to forward information into a method.
Where do I begin to understand the underlying problem?
I believe the answer is found in the way that Visual Studio displays values for objects that are
pass by value
pass by constant reference
The code below assigns the proper value to a. However, for my object, the debugger reports #DEN when I ask it to display thing.x.
method(Thing thing)
{
double a = thing.x;
}
However, when I write:
method(const Thing& thing)
{
double a = thing.x;
}
the debugger reports the expected value for thing.x.
I recognize that there is a difference between pass by value and pass by constant reference. However, in my case I don't think that there is a practical difference.
Without going into too many irrelevant details about a large multi-library project I'm working on I'd like to ask a question about a specific event that occurred in it. I'm using Luabind to have my C++ code interface with my Lua code and I have a class structure with inheritance like so:
GuiWidget
GuiButton : GuiWidget
I've registered both of these classes with Lua via Luabind. Then I do the following, where widget is a pointer to an instance of the GuiWidget class:
lua_newtable(luaState);
luabind::object(luaState, widget).push(luaState);
lua_setfield(luaState, 2, "widget");
lua_setglobal(luaState, "event");
//This line connects to some other code I wrote that just executes a file and handles errors.
luaMachine->doFile(widget->getUserString("eventMouseButtonClick"));
lua_pushnil(luaState);
lua_setglobal(luaState, "event");
Now this same code snippet can handle anything from buttons to scroll bars and even entire windows. So later on in the lua code I call this line of code for when a check box button is clicked:
event.widget:setSelected(not event.widget:getSelected())
This works. Even though the pointer pushed through is a GuiWidget pointer the lua code somehow knows to use functionality unique to GuiButton class for this particular instance. How does it do that? How does it take a widget pointer and automatically know that particular widget is a button? I didn't believe it was possible so it took me a while to arrive at that solution but I figured I'd take a shot in the dark and it worked somehow.
It has been a long time since you asked but i may have an answer for this...
luabind generates internal unique ID for every type you register when you start your executable (+ wrappers etc...)
There is global "map" in LUA_REGISTRYINDEX called __luabind_class_id_map translating typeid to this previously assigned internal unique ID
When you return pointer (GuiWidget) luabind asks for typeid of returned pointer by dereferencing it -> typeid(ptr). This surprisingly returns type_info of GuiButton not GuiWidget (although GuiWidget ptr = new GuiButton();)
Then luabind translates typeid of GuiButton into internal ID and finds class_rep for that in another LUA_REGISTRYINDEX table (__luabind_class_map). class_rep holds how object should be stored on Lua side and other info related to registered c++ class.
Last interesting info for making this to work is, that all pointers on Lua side are stored like so: dynamic_cast(ptr) that later allows for auto casting from that to other classes validated using previous method and inheritance info in class_rep
That is roughly how this implicit casting can be done / is done in luabind library.
All the googling I've done so far has turned up things that are very close but just aren't quite cutting it for what I'm trying to do.
Let me describe this in the most basic way possible:
Imagine you have a C++ class
class A
{
public:
int Method();
int Variable;
};
Now imagine you instantiate A* Foo;
Now imagine you have a .lua file with this 3 line function:
function Test()
local n = Foo:Method();
Foo.Variable = 0;
local m = Foo.Variable;
end
How can you bind the object A* to lua such that all those things are doable?
Pseudocode-wise, my first attempt went like this, partly from copy pasting examples:
In a function only called once, regardless of the number of instances of A:
create newmetatable( MT )
pushvalue( -1 ) (i dont really get this)
setfield( -2, "__index" )
pushcfunction with a static version of Method that unpacks the A* pointer from checkudata
setfield( -2, "Method" )
In an init function called for each instance, e.g. Foo:
create a pointer to Foo with newuserdata
setmetatable( MT )
setglobal with Foo to make the name available to lua
In a test function in main:
pcall a test function with the 3 lines of .lua mentioned above, by global name
When doing this, Foo:Hide(); successfully called my static function, which successfully unpacked the pointer and called its member Hide().
So far so good for :Method().
Then I tried to support the .Variable access. Everyone seemed to be saying to use metatables again this time overriding __index and __newindex and make them a sort of generic Get/Set, where you support certain keys as valid variable links e.g. if( key == "Variable" ) Variable = val;
This also worked fine.
The problem is trying to put those two things together. As soon as you override __index/__newindex with a getter/setter that works on Variable, the Method() call no longer calls the Method() static function, but goes into the __index function you bound instead.
All of that said, how does one support this seemingly basic combination of use cases?
Actual code snippets would be much more appreciated than purely theoretical chatter.
Reminder: please respond using the basic C API only, not third party stuff.
the Method() call no longer calls the Method() static function, but
goes into the __index function you bound instead.
So program it so that if the key exists in the table, return that first, else go for getter/setter.
I'm still relatively new to Objective C and easily confused by the various types. I am using code from the SquareCam sample project, incorporated into a larger project. It works fine, but now I want to save the videoDataOutputQueue, which is of type dispatch_queue_t so that I can use it elsewhere in the project. It has to pass through some C++ code before finally ending up back in Objective C code. Therefore I am trying to add it to a structure that I already have, as a void * (void *videoDataOutputQueue;)
However, I have not found the right way to assign it without getting a EXC_BAD_ACCESS runtime error. Since dispatch_queue_t is a C++ object, can't I just use it's address?
declared in the interface for squarecamviewcontroller:
#interface SquareCamViewController : UIViewController <UIGestureRecognizerDelegate, AVCaptureVideoDataOutputSampleBufferDelegate,UIActionSheetDelegate>
{
AVCaptureVideoPreviewLayer *previewLayer;
AVCaptureVideoDataOutput *dataOutput;
AVCaptureVideoDataOutput *videoDataOutput;
dispatch_queue_t videoDataOutputQueue;
<other stuff>
}
later in the code:
- (void)setupAVCapture
{
<other stuff from the sample code>
MYSTRUCT myStruct = (MYSTRUCT)struct; // make a pointer to the structure
myStruct->videoDataOutputQueue = (void *)videoDataOutputQueue; <<<- bad access here at runtime
<other stuff>
}
Clearly this is not the right way and I don't understand what I am doing. I have some hints from other posts but I'm missing something.
Thanks,
Ken
You have made your question unnecessarily difficult to understand because the "code" you've presented has syntax errors. It's clearly not your real code, so we can't guess what's really supposed to be happening. For example, you use the struct reserved keyword as though it were a value.
Given where you say the bad access occurs, this has nothing to do with the dispatch queue. It looks like your myStruct variable is supposed to be a pointer to a structure of some kind but is just a garbage pointer. So, the attempt to assign a value to one of its fields ends up writing to an invalid memory address. It doesn't really matter what the nature of the field is.
The problem is apparently exactly in the code you omitted as "<other stuff from the sample code>". So, you need to show that. Indeed, you need to show your real code.
Beyond that, dispatch_queue_t is a C type. It's not specific to Objective-C. Therefore, you can use it across all C-based languages. There's no need to use a void*.
A dispatch queue, like all dispatch objects, is reference counted. If you're keeping a long-term reference to it, you need to make sure it stays alive. So, you need to retain it with dispatch_retain(). Likewise, you need to release it when you're done with it using dispatch_release(). (Don't forget to release the old value when you replace a reference you're keeping with another.)
I am trying to understand the programming of Siemens scanner using C++ and given that my C++ skills are limited, I am having problems in understanding many parts of the code provided by the vendor.
Problem 1
For instance, the code uses reference (rMrProt) to object MrProt and notations (such as the use of use of (). and ()[].) are very confusing to me.
For instance:
ImageSamples = rMrProt.kSpace().baseResolution()
ImageSize = rMrProt.sliceSeries()[0].readoutFOV()
Some explanation of these statements would be appreciated.
All information regarding object MrProt are in “MrProt.h”, “MrProt.dll”, “MrProt.lib”. All these files have been shared at:
https://docs.google.com/open?id=0B0Ah9soYnrlIYWZkNDU2M2EtYTNmNC00YTc5LTllMzItYzIyMWU4M2ZhY2Fi
Problem 2
Also, I have been trying to read MrProt.dll and MrProt.lib without any success. Only now, I came to know of dumpbin. Any help would be appreciated.
Problem 3
Another confusion that I have is related to some part of MrProt.h itself. There is a statement in MrProt.h:
class __IMP_EXP MrProt: public MrProtocolData::MrProtDataDelegate
{
typedef MrProtocolData::MrProtDataDelegate BasicImplementation;
public:
MrProt();
MrProt(const MrProt& rSource);
…
….
}
Here, __IMP_EXP, I guess that it’s some compiler specific stuff.. some decoration etc. But, I still have no idea what to make of this.
Problem 1.
rMrProt.sliceSeries()[0].readoutFOV()
means
Take rMrProt's sliceSeries member and call that. Apparently, it returns an array-like object, something that can be indexed.
From the result, take the first element ([0]). That's some kind of object.
On that element/object, call readoutFOV.
Problem 2. You're not really supposed to read binary files. There should be documentation with them.
1)
ImageSamples = rMrProt.kSpace().baseResolution()
This is just method chaining. You call the method kSpace() on rMrPrto which returns an object, and you call baseResolution() on that object.
2) Those are binary files. What would you expect to see? To read them you'd have to be an expert in asm or at least know some low-level concepts.
3) __IMP_EXP is a common type of directive that tells the compiler that the class is either exported or imported.
It expands to _declspec(dllimport) or _declspec(dllexport), depending on whether the definition of the class is in the current module or another module.
identifier() is a method/function call
identifier[i] returns the i'th element in an array.
identifier()[i] returns the i'th element of the array returned by identifier()
I can only help on problem 1:
if the return value of rMrProt.kSpace() is a struct. instead of saving it to a struct and then access it's member you can directly access a member of his with rMrProt.kSpace().MemberName
same for rMrProt.sliceSeries() which I guess is returning an array. so rMrProt.sliceSeries()[0] will access the first value in the returning array.