Before April 2019, it was possible for a Lua script to reflect the methods and properties of a LuaBridge class using string keys __parent, __class, __propget, and __propset. This was an incredibly useful tool for creating test scripts and development tools to maintain a large class framework exported into Lua.
From looking through the release notes of LuaBridge, it seems the string keys were removed for security reasons. But I find myself placing more priority on the ability to reflect classes from scripts than on whether scripts can muck around in the object model. Especially in dev mode.
The LuaBridge Reference Manual implies there is a way for a C/C++ program to expose the metatables, but I haven't been able to figure out how to do it. I am quite new to interfacing between C and Lua (or LuaBridge), so I'm not surprised that I am perplexed. If anyone could share an example of how to do this, I would appreciate it.
Since no one seems to have a good suggestion, I realized I could roll my own reflection of the names of properties, methods, and constants. For my purposes I don't really need to execute or access them.
So rather than muck around inside LuaBridge I added __class, __propget, and __propset static properties to every class in my framework. These return a table implemented with std::map which LuaBridge supports. The tables simple have the names as keys and a dummy value.
One caveat I discovered is that you have to add static properties to derived classes when creating the derived class with deriveClass. If you try to add them later (using beginClass), LuaBridge throws an assert.
Related
The DYNAMIC FACTORY pattern describes how to create a factory that
allows the creation of unanticipated products derived from the same
abstraction by storing the information about their concrete type in
external metadata
from : http://www.wirfs-brock.com/PDFs/TheDynamicFactoryPattern.pdf
The PDF says:
Configurability
. We can change the behavior of an application by just changing its configuration
information. This can be done without the need to change any source code (just change the descriptive information about the type in the metadata repository) or to restart the application (if caching is not used – if caching is used the cache will need to be flushed).
It is not possible to introduce new types to a running C++ program without modifying source code. At the very least, you'd need to write a shared library containing a factory to generate instances of the new type: but doing so is expressly rules out by the PDF:
Extensibility / Evolvability
. New product types should be easily
added without requiring neither a
new factory class nor modifying
any existing one.
This is not practical in C++.
Still, the functionality can be achieved by using metadata to guide some code writing function, then invoking the compiler (whether as a subprocess or a library) to create a shared library. This is pretty much what the languages mentioned in the PDF are doing when they use reflection and metadata to ask the virtual machine to create new class instances: it's just more normal in those language environments to need bits of the compiler/interpreter hanging around in memory, so it doesn't seem such a big step.
Yes...
Look at the Factories classes in the Qtilities Qt library.
#TonyD regarding
We can change the behavior of an application by just changing its configuration information.
It is 100% possible if you interpret the sentence in another way. What I read and understand is you change a configuration file (xml in the doc) that gets loaded to change the behaviour of the application. So perhaps your application has 2 loggers, one to file and one to a GUI. So the config file can be edited to choose one or both to be used. Thus no change of the application but the behaviour is changed. The requirement is that anything that you can configure in the file is available in the code, so to say log using network will not work since it is not implemented.
New product types should be easily added without requiring neither a new factory class nor modifying any existing one.
Yes that sounds a bit impossible. I will accept the ability to add ones without having to change the original application. Thus one should be able to add using plugins or another method and leave the application/factory/existing classes in tact and unchanged.
All of the above is supported by the example provided. Although Qtilities is a Qt library, the factories are not Qt specific.
About the last year I did Java(Android)-programming, and did C# the Year before that. About a month now I'm learning C++, and since I got over friends, inheritance and stuff, I got a few questions, since I haven't been working with it up until now:
Is there a way for a class to define friends later on, because they need to exchange information or something. e.g. is there a way to define a 'random' friend later on? what do you need for that? The function's name or the address of the class?
Or is there generally a way to change the code from the program itself, so that it won't be necessary to recompile? e.g. creating new functions, classes or so?
I'd be very happy about any answer about that.
What you want to do is not possible with C++. If you need that sort of dynamically changing the program, you are better advised using a more dynamic higher-level language like Lisp.
friends can only be added to a class by modifying its source code. This is a feature, not a bug.
There are two ways to extend functionality like that.
Use dynamically loaded modules with the extended functionality. These modules supply a specific interface, and can be compiled separately from the main program.
Add support for scripting - allow users to add write scripts, and run them from inside your program.
The first solution is easier, depending on how much control you want to give those scripts.
I have looked at multiple sources and I just do not understand them. Mostly all of them are either using a library like luaBind (Which I do not want to use because it relies on Boost) or they are not already instanced objects in C++ but rather created in Lua directly.
I have a Player class, which is wrapped in another class to handle Lua calling. I have created a std::vector list of both these objects in my initialization of the application.
So basically I do not want the Lua script to be creating these player objects I would just like to create a function getPlayer() which then returns the Lua wrapped object. I have no idea where to start with defining the Lua wrapped object for Lua to call nor do I know how to return an instance of the object to Lua so I can use calls from it.
Here's an example of what I would like my Lua script to look like:
player = getPlayer(1) -- Returns the Lua wrapped object from C++ where 1 is the object's index in the std::vector list
print("Player's name: ", player:name()) -- Print's the player's name
Could someone point me to a decent tutorial that explains how to do this. I am pretty sure that this isn't some sort of "Never been done and why would you want to" case so surely there must be at least one tutorial out there. I have been searching for about 2 days now with no positive results.
This isn't a Never been done task, but companies which they use Lua have been already done lots of changes and improvements on the raw source of Lua to make it fit in the place that they want. Since all of us programmers are not that cool to do such stuffs on third-parties sources, we have to use whatever exists out there. You think Crytek is using the exact same version of Lua which is resided on its website's repository? No sir.
You can make this happen by using userdata. Or you can use meta tables. There is also another piece of code named Luna which it helps you to achieve faster.
Otherwise, it's all Luabind, and believe me you're going to end up using it one way or another. Besides, its use of Boost is not that broad and there is going to be just 200kb added to the final executable. Check this address if you want to use Luabind sometime, it's really a good article on the web. http://blog.nuclex-games.com/tutorials/cxx/luabind-introduction/
If you're too bored with Lua, I may suggest you to use squirrel as an alternative to Lua. Personally, I prefer squirrel more than Lua because of its C like syntax and its abilities which they are the ones that we want. Besides, you can even declare constants and use real classes in its context which Lua is pretty failed at this. The funny thing about squirrel is that the designer is a guy that he has been working on FarCry on developing Lua for its engine.
I'm developing a game and now I want to make script system for it.
Now I have abstract class Object which is inherited by all game objects. I have to write a lot of technical code, add new object type into enum, register parser function for each object (that function parses object's params from file).
I don't want to make such work. So the idea is to get some script system (boost.python for example, because I'm using boost in my project). Each object will be a simple python-script, at c++ side I just load and run all that scripts.
Python isn't hard -typed so I can register functions, build types dynamically without storing enum, etc. The only bad part is writing a lot of binding-code but It makes only once.
Are my ideas right?
Can you give us a rough idea of how large the game is going to be?
If you're not careful, you could give yourself a lot of extra work without much benefit, but with some planning it sounds like it might help. The important questions are "What parts of the program do I want to simplify?", "Do I need a scripting language to simplify them? and "Can the scripting language simplify them?".
You mentioned that you don't want to have to manually parse files. Python's pickle module could handle serialization for you, but so could .NET. If you're using Visual Studio, then you may find it easier to write the code in C# than in Python.
You should also look for ways to simplify your code without adding a new language. For example, you might be able to create a simple binary file format and store your data structures without much parsing. There are probably other things you can do, but that would require more detailed knowledge of the program.
Is it possible to implement monkey patching in C++?
Or any other similar approach to that?
Thanks.
Not portably so, and due to the dangers for larger projects you better have good reason.
The Preprocessor is probably the best candidate, due to it's ignorance of the language itself. It can be used to rename attributes, methods and other symbol names - but the replacement is global at least for a single #include or sequence of code.
I've used that before to beat "library diamonds" into submission - Library A and B both importing an OS library S, but in different ways so that some symbols of S would be identically named but different. (namespaces were out of the question, for they'd have much more far-reaching consequences).
Similary, you can replace symbol names with compatible-but-superior classes.
e.g. in VC, #import generates an import library that uses _bstr_t as type adapter. In one project I've successfully replaced these _bstr_t uses with a compatible-enough class that interoperated better with other code, just be #define'ing _bstr_t as my replacement class for the #import.
Patching the Virtual Method Table - either replacing the entire VMT or individual methods - is somethign else I've come across. It requires good understanding of how your compiler implements VMTs. I wouldn't do that in a real life project, because it depends on compiler internals, and you don't get any warning when thigns have changed. It's a fun exercise to learn about the implementation details of C++, though. One application would be switching at runtime from an initializer/loader stub to a full - or even data-dependent - implementation.
Generating code on the fly is common in certain scenarios, such as forwarding/filtering COM Interface calls or mapping OS Window Handles to library objects. I'm not sure if this is still "monkey-patching", as it isn't really toying with the language itself.
To add to other answers, consider that any function exposed through a shared object or DLL (depending on platform) can be overridden at run-time. Linux provides the LD_PRELOAD environment variable, which can specify a shared object to load after all others, which can be used to override arbitrary function definitions. It's actually about the best way to provide a "mock object" for unit-testing purposes, since it is not really invasive. However, unlike other forms of monkey-patching, be aware that a change like this is global. You can't specify one particular call to be different, without impacting other calls.
Considering the "guerilla third-party library use" aspect of monkey-patching, C++ offers a number of facilities:
const_cast lets you work around zealous const declarations.
#define private public prior to header inclusion lets you access private members.
subclassing and use Parent::protected_field lets you access protected members.
you can redefine a number of things at link time.
If the third party content you're working around is provided already compiled, though, most of the things feasible in dynamic languages isn't as easy, and often isn't possible at all.
I suppose it depends what you want to do. If you've already linked your program, you're gonna have a hard time replacing anything (short of actually changing the instructions in memory, which might be a stretch as well). However, before this happens, there are options. If you have a dynamically linked program, you can alter the way the linker operates (e.g. LD_LIBRARY_PATH environment variable) and have it link something else than the intended library.
Have a look at valgrind for example, which replaces (among alot of other magic stuff it's dealing with) the standard memory allocation mechanisms.
As monkey patching refers to dynamically changing code, I can't imagine how this could be implemented in C++...