Say I have the address of a table - how would I "cast" a table variable to it? I'm not concerned about "bad practice" or crashes because this is just an individual problem.
I want to do something like
lua_table tab = *(lua_table*)0xaddr
...but within the Lua global environment.
I understand how bad this is but I really need to know if this is possible. It may not be the best way to do what I'm trying to do, but I'm quite certain it's the easiest and that it will work if this is possible. I am using Lua 5.1.4.
Lua exposes no API for doing this.
It would be easier and much more robust to fix your design rather than trying to force this to work.
In order to do what you're attempting, you must:
Get a pointer to the Lua table's data structure. I'm sure you believe that you already have such a pointer. But there's nothing in Lua that guarantees that the pointer you have obtained (through some means) is actually a pointer to the table data structure. It could be a pointer to something else. So you need to hunt through Lua's internals to make sure that wherever you're getting this pointer from is giving you a pointer to the actual object.
Find the correct type, declared within Lua's internals. There is some C type (Lua's written in C, not C++) that Lua uses to represent the main table data structure. You will have to track down this struct definition and use that.
A cursory examination of the Lua library suggests that the main table data structure is defined in lobject.h, under the name Table.
Find the internal APIs that Lua uses to manipulate this table correctly. It's obviously some kind of hash table, but you're going to need to use Lua's functions to actually do anything with it.
A cursory examination of Lua's internals suggests that this code would be found in ltable.h. However, there are probably more APIs than that. Also, do note that many of those APIs take a lua_State, so they may be doing some stack fiddling.
You will also need to look through Lua's API so that you can learn how to use them without breaking the table. Lua may have certain expectations about when certain functions are called or the order between them or whatever. Break these at your own peril.
Even then, this:
Table tab = *(Table*)0xaddr
Will never work. Or at least, not the way you mean for it to. Lua is written in C. Which means that Table is not going to work like a C++ value type. Copying it will only do a bitwise copy. So modifying tab will only modify your local copy of those values. If those are pointers to other data structures, that may be OK, since your pointers and the original pointers point to the same data structures. But if you perform some operation that changes the Table::flags field on the table, for example, the table stored in Lua will not be affected, only your local tab copy will be.
You have to manipulate the object as a pointer, not a copy of the original.
Table *tab = reinterpret_cast<Table*>(0xaddr);
Related
I successfully integrated Lua into my C my application, giving scripting access to users. Now my problem: how can I prevent double free or bad access violations?
I already implement Init and Free functions for each struct, for example:
structaInit
structaFree
I also track every time a struct pointer is linked to another, incrementing the reference count which is present in all of my structs.
However the users could always do something like this in Lua:
a = structaInit();
b = structbInit();
structbSetA( b, a ); -- This add ++a.reference
a.reference = 0;
a = structaFree( a ); -- If a->reference == 0 then I free
-- Then struct b->a is still a valid pointer but that have been free.
Is there anyway I can prevent this from happening?
The problem has to do with ownership. Let's take your Lua scripts:
a = structaInit();
b = structbInit();
This creates C objects that Lua now owns. Lua will decide when to free the memory for these objects.
So what about this?
structbSetA( b, a ); -- This add ++a.reference
First of all, structbSetA should be a member of b, via a metatable (so it becomes b:setA(a)). But more importantly, who owns a?
Lua does. Because it must own A; Lua cannot fully relinquish ownership of an object that is still in Lua memory. This means that your internal reference count is ultimately meaningless; the only one that matters is Lua's.
If you intend to store the value of a within b, such that b can reference a so long as b is still alive, then you need to create this relationship through Lua methods. You can't just stick the C pointer to a in b and expect everything to go well.
The easiest way to do that is to, for each object you create, make a table in the Lua registry that stores the Lua object for any references it has. When an object is destroyed, you go into the Lua registry and remove this table from it, thus leading to the destruction of any referenced Lua objects. Obviously, you will need to change this value when it is modified by later calls to structbSetA.
Also, why are you exposing this to Lua:
a.reference = 0;
That's a terrible API. Lua code should never have to deal with a reference count. You should also never expose an explicit "free" method to Lua, unless you need Lua to release some resource immediately after it is finished using it. And that should only be necessary for OS-type resources like FILE handles and such. For a regular object, let the garbage collector do its job.
Do not expose C-isms to Lua code. Let Lua code look like Lua code.
In this case it comes down to programming practice you do not really want to prevent it, you actually want to let it error out because that way the person using your scripts knows that they are doing something wrong (same way in obj-c it crashes when you over-release). If you don't want this to happen you might have to keep track of all active pointers on the heap to your structs in a linked list or some structure but I don't think it's worth it.
I'm having problems with luabind. I define a std::map to allocate objects created in lua. I publish this map as a global object in lua in this way:
luabind::globals(L)["g_SceneManager2D"] = this;
After that, this object is used into a function into lua, where many objects are created and inserted into this map. The problem comes when lua function ends and luabind returns the control to C++ side program, because automatically all contents of the map are lost.
I was looking for the error. I keep the lua context alive, so this object must exists.
Could you helpme??
Many thanks :)
I suggest use a shared_ptr<>(this) rather than raw this. boost::shared_from_this might help. Make sure your class is registered using Luabind too, and that the class_ is specified as held by a shared_ptr.
Another fun idea might be to make your Lua function just generate the "map" as a Lua table, return it, and you can iterate over it in C++ to build your std::map.
If I understand your problem correctly, it seems you are creating objects in Lua, which you then insert into the map (either through Lua or C++) and subsequently lose. Without some more code, it's hard to tell exactly what the problem is. However, I would first look to make sure that those objects are indeed being created (double check it) and then I would check to see that Lua isn't garbage collecting them. If Lua is indeed garbage collecting those objects, then you won't see them on the C++ side because they're, well, gone.
If it helps, I'm finishing up a project which does something similar. I had to create and retrieve C++ objects from Lua, but instead of creating the objects in Lua, I just called C++ functions to do it for me, sending any necessary data in the Lua call (bound by Luabind). Those (C++) functions indexed the objects by IDs into hash tables and the IDs were returned to Lua in case it needed to retrieve the object script-side for operations. This setup makes it easier (and safer) to handle memory stuff correctly and prevents Lua from garbage collecting your objects.
I have a class which defines a historical extraction on a database:
class ExtractionConfiguration
{
string ExtractionName;
time ExtractionStartTime;
time ExtractionEndTime;
// Should these functions be static/non-static?
// The load/save path is a function of ExtractionName
void SaveConfigruation();
void LoadConfiguration();
}
These ExtractionConfigurations need to be saved to/loaded from disk. What is the best way of organising the save/load functions in terms of static/non-static? To me, it is clear that SaveConfiguration() should be a member function. However with LoadConfiguration(), does it make more sense to call
ExtractionConfiguration newExtraction;
newExtraction.LoadConfiguration();
and have a temporary empty instance or make the load function static
static ExtractionConfiguration LoadConfiguration(string filename);
and just call
ExtractionConfiguration newExtraction = ExtractionConfiguration::LoadConfiguration(filename);
which feels neater to me, but breaks the 'symmetry' of the load/save mechanism (is this even a meaningful/worthwhile consideration?).
I suppose asking for the 'best' answer is somewhat naive. I am really trying to get a better understanding of the issues involved here.
P.S. This is my first question on SO, so if I have not presented it correctly, please let me know and I will try and make the problem clearer.
You should consider using Boost.Serialization style serialization function that avoids having separate functions for saving and loading (even if you don't use the library itself).
In this approach you can pass the function any type of object that has operator&, to perform an operation on all the member variables. One such object might save the data to a file, another might load from a file, third might print the data on console (for debugging, etc).
If you wish to keep separate functions, having them as non-static members might be a better option. For the saving function this is obvious, but loading is a different matter because there you need to construct the object. However, quite commonly loading is done by default-constructing and then calling the load non-static member function, for symmetry reasons, I guess.
Having the loading as a function that returns a new object seems better in some ways, but then you need to decide how it returns the object. Is it allocated by new, or simply returned by value? Returning by value requires the object to be copyable and returning a pointer mandates the resource management scheme (cannot just store the object on stack).
I have C++ objects and I have Lua objects/tables. (Also have SWIG C++ bindings.)
What I need to be able to do is associate the two objects so that if I do say
CObject* o1 = getObject();
o1->Update();
it will do the equivalent Lua:
myluatable1.Update();
So far I can imagine that CObject::Update would have the following code:
void CObject::Update(){
// Acquire table.
// ???
// Do the following operations on the table.
lua_getfield(L, -1, "Update");
lua_pcall(L, 0, 0, 0);
}
How would I store/set the Lua table to be used, and what would go in the // ??? above to make the Update call work?
I cant believe nobody noticed this!
http://www.lua.org/pil/27.3.2.html
A section of the Lua API for storing references to lua objects and tables and returning references for the purposes of being stored in C structures!!
I am curious for the reasons of this "reverse SWIG"...
The objects in Lua live within the Lua contexts, so at a minimum you would need to store "L" inside your object.
The issue of passing the "table pointer" is a bit more delicate - even though Lua allows to retrieve the pointer off the Lua stack (using lua_topointer()), there is no way of putting that back. Understandingly - because otherwise one would also need to check that the pointer does point to a valid object, etc, etc.
What you might do however, is to store the references to the tables in the global table, the index being the lightuserdata being the pointer to your object. Then by having the Lua state, and the name of the global array, you can retrieve the reference to the table and push it onto the Lua stack for that context.
This is sketchy, and I haven't even touched the question of garbage-collecting with this construct.
But in any case this is not going to be the speed racer performance-wise, and looks like a lot of boilerplate C++ code to me. I'd try to reconsider the approach and push some of what you want to do into the Lua domain.
p.s. looks like it is the third question which seems almost a dupe of the previous two ones, here and here are the previous ones. If those were not answered fully, would have been better to edit them/add the bounty to accumulate the answers.
I am writing a perl script to parse a mysql database schema and create C++ classes when necessary. My question is a pretty easy one, but us something I haven't really done before and don't know common practice. Any object of any of classes created will need to have "get" methods to populate this information. So my questions are twofold:
Does it make sense to call all of the get methods in the constructor so that the object has data right away? Some classes will have a lot of them, so as needed might make sense too. I have two constrcutors now. One that populates the data and one that does not.
Should I also have a another "get" method that retrieves the object's copy of the data rather that the db copy.
I could go both ways on #1 and am leaning towards yes on #2. Any advice, pointers would be much appreciated.
Ususally, the most costly part of an application is round trips to the database, so it would me much more efficient to populate all your data members from a single query than to do them one at a time, either on an as needed basis or from your constructor. Once you've paid for the round trip, you may as well get your money's worth.
Also, in general, your get* methods should be declared as const, meaning they don't change the underlying object, so having them go out to the database to populate the object would break that (which you could allow by making the member variables mutable, but that would basically defeat the purpose of const).
To break things down into concrete steps, I would recommend:
Have your constructor call a separate init() method that queries the database and populates your object's data members.
Declare your get* methods as const, and just have them return the data members.
First realize that you're re-inventing the wheel here. There are a number of decent object-relational mapping libraries for database access in just about every language. For C/C++ you might look at:
http://trac.butterfat.net/public/StactiveRecord
http://debea.net/trac
Ok, with that out of the way, you probably want to create a static method in your class called find or search which is a factory for constructing objects and selecting them from the database:
Artist MJ = Artist::Find("Michael Jackson");
MJ->set("relevant", "no");
MJ->save();
Note the save method which then takes the modified object and stores it back into the database. If you actually want to create a new record, then you'd use the new method which would instantiate an empty object:
Artist StackOverflow = Artist->new();
StackOverflow->set("relevant", "yes");
StackOverflow->save();
Note the set and get methods here just set and get the values from the object, not the database. To actually store elements in the database you'd need to use the static Find method or the object's save method.
there are existing tools that reverse db's into java (and probably other languages). consider using one of them and converting that to c++.
I would not recommend having your get methods go to the database at all, unless absolutely necessary for your particular problem. It makes for a lot more places something could go wrong, and probably a lot of unnecessary reads on your DB, and could inadvertently tie your objects to db-specific features, losing a lot of the benefits of a tiered architecture. As far as your domain model is concerned, the database does not exist.
edit - this is for #2 (obviously). For #1 I would say no, for many of the same reasons.
Another alternative would be to not automate creating the classes, and instead create separate classes that only contain the data members that individual executables are interested in, so that those classes only pull the necessary data.
Don't know how many tables we're talking about, though, so that may explode the scope of your project.