So, I want to be able to modify already instanced C++ objects in a scripting language. I have been looking at Lua with LuaBind and Python with SWIG or Boost::Python, but all I see is how to make new instances of the objects, but I want to modify already existing ones.
Example:
C++:
Player playerOne = new Player();
Scripting Language :
playerOne.Transform.x += 5;
Is this possible, and if so, wat would you suggest as a good Language/library to achieve this with?
In my main project we use LuaBind, and it works pretty well. We do basically what you're asking to do. We have existing C++ objects where we want behavior extended in various ways, but it would be a lot of work and risky to do those changes in behavior in the C++ code for the object itself.
So in your example, you'd want at least 2 C++ wrapper classes - one that represents the 'Game' that allows you to write an API function to return players, and a wrapper class that wraps the C++ player class that you can return to lua. Each wrapper function would have api functions/properties that would fiddle with the individual object it's wrapped internally that lua could call and pass values to. Here is a link to an article giving you pretty straightforward examples of using LuaBind and what it looks like:
http://blog.nuclex-games.com/tutorials/cxx/luabind-introduction/
I recently needed to do the same thing. I also considered (and used) Boost.Python but personally (as much as I love Boost) I felt it was a little overkill to drag in half the Boost library to get one feature.
So, if you're interested, I recently implemented a very light-weight Python wrapper library called ECS:Python. ECS:Python (Embedded C++ Scripting with Python) is designed specifically for C++ developers that wish to expose objects FROM a C++ application TO an embedded Python interpreter for interactive scripting.
Its free (BSD) and open source: http://sourceforge.net/projects/ecspython
There is no mechanism that can magic values into a scripting language from the host language. If you want a particular object instances to be accessible in the scripting language, it must be given to the scripting language via some function.
This is no different from any other properly encapsulated C++ type. If object A creates and stores some instance T, then the only way object B can get it is if it calls a function on A that returns T.
I was having the problems in my project. Have a look at my post in the Ogre3d forums:
http://www.ogre3d.org/forums/viewtopic.php?f=5&t=41631&p=332200&hilit=mrmclovin#p405204
Code example:
int main (int argc, char * const argv[])
{
try
{
// Initialize the python interpreter
Py_Initialize();
// Create a module dynamically
object module((handle<>(borrowed(PyImport_AddModule("NameOfMyModule")))));
// Retrieve the module's namespace
object main_namespace(module.attr("__dict__"));
// Put a c++ class named "Car" exported using boost.python into our module
main_namespace["Car"] = class_<Car>("Car")
.def("drive", &Car::drive)......;
// The class car now exists in a dynamic module
// and that module is accessable everywhere as longs as the python interpreter exists
// Create a instance of Car here
Car* myCar = new Car(...);
// Now simply add it to the module. Make sure you have exposed class Car before adding instances
main_namespace["car_instance"] = object(ptr(myCar)); // the boost python ptr() class make sure not to copy the pointee but only copy pointer adress
}
catch( error_already_set )
{
PyErr_Print();
}
return 0;
}
Related
I have a Linux C++ dynamic library, which is required to pass a compound structure to python, and receive result structure from python to be transferred up to caller application.
To get the python interpreter "alive" after library API function returns back to caller application, I decided to use singleton class (using getInstance...)
For C/Python API I'm (trying to...) using pybind11 embedded module mechanism
Question is how to connect the embedded module within the singleton class, simply meaning how to invoke it from there (also with passed arguments)?
Looked at "calling-embedded-function-in-class-method-using-pybind11", but it don't answer my question
Seems I found the answer
Although I'm working on a Linux project, I find this link:Embedding Python in a C++ project with Visual Studio, with its sample project, very educational,
and looking back at pybind11 embedded documentation, section 13.4 at the PDF, shows it is simply to do so:
Include "py::module" member at C++ class which would be initialized with py::module::import("module_name");
and then call the C'tor etc. using it
such as:
// class member
py::module mModule;
and
//initialization
mModule = py::module::import("module_name");
mModule .attr("initialize").call(mArg1, mArg2);
Since this is a singleton class within a library, rather than regular example of main(), for the interpreter lifetime, I find it better to use:
py::initialize_interpreter();
{
//call py code...
}
and then call
py::finalize_interpreter(); at the destruction of this instance
rather than, regular py::scoped_interpreter guard{}; which finishes its lifetime at the end of the scope
---Context---
I want to have a class called "fileProcessor". This class is completely static and merely serves as a convinient namespace (within my normal library namespace) for some global function. This is a basic blueprint of the class with only the relevant stuff
class fileProcessor{
private:
lua_State* LUA_state;
public:
static std::variant<type1,type2> processFile(const char* filePath,const char* processorScript);
}
Please note again that I ommitted most of the stuff from the class so if anything seems odd ignore it.
What process file is supposed to do is:
Read the filePath file, storing all directives including it (this is my own filetype or style of syntax. This is already handeled correctly). The directives are stored with strings, one for the command and one for everything after it.
Read the script file and check if it has a commented out fileProcessor line at the top. This is to make sure that the lua script loaded is relevant and not some random behaviour script
Load and compile the lua script.
Make all read directives available (they are saved in a struct of 2 strings as mentioned before)
Run the file and recieve a object back. The object should only be of types that I listed in the return type (variant)
I am having problems with step 4 and one vital part of the scripting.
---Question---
How can I make the creation of a full new object of type1 or type2 possible within lua, write to it from within lua and then get it back from the lua stack into c++ and still know if its type1 or type2?
---No example provided since this question is more general and the only reason I provided my class is for context.---
It seems like you are trying to do it the other way around. I quote a part of this answer:
...you are expecting Lua to be the primary language, and C++ to be the client. The problem is, that the Lua C interface is not designed to work like that, Lua is meant to be the client, and all the hard work is meant to be written in C so that Lua can call it effortlessly.
If you are convinced there is no other way that doing it other way around you can follow the workaround that answer has given. Otherwise I think you can achieve what you need by using LUA as it meant to be.
LUA has 8 basic types (nil, boolean, number, string, userdata, function, thread, and table). But you can add new types as you require by creating a class as the new type in native C++ and registering it with LUA.
You can register by either:
Using some LUA helper for C++ like luna.h (as shown in this tutorial).
Pushing a new lua table with the C++ class (check this answer).
Class object instance is created in your native C++ code and passed to LUA. LUA then makes use of the methods given by the class interface.
I'm not sure if my question makes any sense, but I certainly know it is near impossible to get the results from Google. Firstly, what I do not want. I don't want to call some function that prints "hello world" or adds two numbers together, I want to load a Lua script from a C++ program, but allow the script to modify variables of the C++ program, using functions. For example, imagine I have a C++ program like this:
class Foo
{
private:
int number = 0;
public:
void setNumber(const int& newNumber) {number = newNumber;}
}
int main()
{
Foo foo;
//Load and execute Lua script, with foo object
return 0;
}
How could I allow the Lua script to do foo.setNumber() (preferably without foo.)? This may be a very simple question, but as mentioned above, almost all information on Google when searching "Call C++ Function from Lua" assume there is no program, but just a .cpp/hpp file with some functions that you want to call.
I'm on Linux (Ubuntu), but the program needs to compile on all platforms (Windows and Mac)
This is asked here fairly regularly.
To roll your own binding you should:
Master Lua metatables completely.
Read the Programming in Lua stuff on the C API, particularly the part on classes. Alternatively you can read the manual, read the source (API headers especially), and do some googling, but the book will probably save you some time.
Broadly, you expose a C++ class instance to Lua by creating a Lua "userdata" containing a pointer to the class instance and passing this to the Lua script. A userdata is an opaque type; the Lua script can't actually do anything with it (other than pass it around) unless you give it a metatable. At the very least you must implement the __index metamethod on the userdata, which allows your C++ code to intercept attempts to index the userdata and return something meaningful, and the __gc metamethod, which allows your C++ code to delete the exposed C++ object when the corresponding Lua userdata is garbage collected.
For instance, you create a function called createFoo which creates a Foo instance, wraps the pointer as a userdata, applies a metatable implementing __index to it, and returns it to the Lua script.
When the user runs foo.setNumber, your C++ __index metamethod is called with the userdata and the string "setNumber". It's up to you what you return and this determines what foo.setNumber evaluates to in the Lua script. You want foo.setNumber to evaluate to a lua_CFunction which expects a Foo userdata as its first parameter, so that your class methods can be called idiomatically from Lua (i.e. foo:setNumber(12), which is syntax sugar for foo.setNumber(foo, 12)).
It's a very low level and manual process, and once you get the hang of it you're going to end up create a library/templates/macros whatever to do the boilerplate for you. At that point you may want to evaluate the myriad C++ binding libraries that exist. However, thanks to the Law of Leaky Abstractions it's a very good idea to learn to do this manually first.
I had a script with:
Custom language used only for data
Was loaded using a Script class from C++
I had tags like Type, etc
An interface to get a value for a tag - Script::GetValue(Tag, T& value)
The script was used like this:
Script* script("someFile");
script->GetValue("Type", type);
Object* obj = CreateObject(type);
obj->Load(script);
Where Load functions from object was used to load the rest of obj parameters.
Now I changed the script language to lua. My questions is:
Should I keep this way of creating objects(use lua only for data) or should I expose the factory in lua and use it from lua, something like this(in lua):
CreateObject("someType")
SetProperty(someObj, someProperty, someValue)
First of all I want to know which is faster, first or second approach. Do you have other suggestions? Because I'm refactoring this part I'm open to other suggestions. I want to keep lua because is fast, easy to integrate, and small.
You may allow your script environment to create C++ objects or not, depending on your needs.
tolua++ uses all the metatable features to allow a very straightforward manipulation of your c++ types in lua.
For example, this declaration :
// tolua_begin
class SomeCppClass
{
public:
SomeCppClass();
~SomeCppClass();
int some_field;
void some_method();
};
// tolua_end
Will automatically generate the lua bindings to allow this lua scipt :
#!lua
-- obj1 must be deleted manually
local obj1 = SomeCppClass:new()
-- obj1 will be automatically garbage collected
local obj2 = SomeCppClass:new_local()
obj1.some_field = 3 -- direct access to "some_field"
obj2:some_method() -- direct call to "some_method"
obj1:delete()
The advantage of this technique is that your lua code will ve very consistent with the relying C++ code. See http://www.codenix.com/~tolua/tolua++.html
In situations like that, I prefer to setup a bound C function that takes a table of parameters as an argument. So, the Lua script would look like the following.
CreateObject{
Type = "someType"'
someProperty = someValue,
-- ...
}
This table would be on top of the stack in the callback function, and all parameters can be accessed by name using lua_getfield.
You may also want to investigate sandboxing your Lua environment.
The first approach would most likely be faster, but the second approach would probably result in less object initialization code (assuming you're initializing a lot of objects). If you choose the first approach, you can do it manually. If you choose the second approach you might want to use a binding library like Luabind to avoid errors and speed up implementation time, assuming you're doing this for multiple object types and data types.
The simplest approach will probably be to just use Lua for data; if you want to expose the factory and use it via Lua, make sure it's worth the effort first.
Currently I know how to have C++ objects instantiated and passed around in Lua using SWIG bindings, what I need is the reverse.
I am using Lua & C++ & SWIG.
I have interfaces in C++ and objects in lua, that implement methods which do the same job and have the same structure. I would like to be able to instantiate these objects in lua yet pass them around in C++ using pointers to that interface which they resemble.
As such I can imagine creating a c++ implementation of the interface which would act as a handler for said lua object, yet I don't know how to do this. The class would act as the lua objects representative or proxy in the C++ world.
To clarify I shall start with the following example code used in an answer to a similar question I asked:
C++ code:
// Represents a generic bank account
class Account {
virtual void deposit(double amount) = 0;
};
Lua code:
SavingsAccount = { balance = 0 }
SavingsAccount.deposit = function(amount)
SavingsAccount.balance = SavingsAccount.balance + amount
end
-- Usage
a = SavingsAccount
a.balance = 100
a.deposit(1000)
Now say that I have a class in C++ called Bank:
class Bank {
void AddAccount(Account* a);
};
What I would like here is a mechanism for doing the following in lua:
SavingsAccount = { balance = 0 }
SavingsAccount.deposit = function(amount)
SavingsAccount.balance = SavingsAccount.balance + amount
end
-- Usage
a = SavingsAccount
bank:AddAccount(a)
If I need to take an extra step such as instantiating a C++ class to act as a proxy and pass it the lua table with all my lua functions etc, I can imagine it looking like this:
C++ code:
// Represents a generic bank account
class ProxyAccount : public Account {
virtual void deposit(double amount);
};
Lua code:
SavingsAccount = { balance = 0 }
SavingsAccount.deposit = function(amount)
SavingsAccount.balance = SavingsAccount.balance + amount
end
-- Usage
a = SavingsAccount
a.balance = 100
a.deposit(1000)
proxy = program.ProxyAccount()
proxy.settable(a)
bank:AddAccount(p)
The problem here being I have no idea how I would implement the ProxyAccount class, or even what the function signature of settable would look like...
I'm not familiar with SWIG (I know what it is but have never used it) so this may not be the answer you are looking for.
I've been working on a C++ project and have had success using luabind. It allows you to subclass C++ objects with Lua objects. You might want to give it a try and see if it works for you.
What I seem to gather from your examples and the discussions is that you are expecting Lua to be the primary language, and C++ to be the client. The problem is, that the Lua C interface is not designed to work like that, Lua is meant to be the client, and all the hard work is meant to be written in C so that Lua can call it effortlessly.
Now, the important question is: why don't you want to have a C representation of the object, and prefer to have it in Lua? Since C++ is a much lower level language, and object definitions must be static, and Lua dynamically defines its "objects" it is much easier to have Lua adapt to C++ objects.
Another issue I see is that you seem to be designing your Lua code in a very Object Oriented manner. Remember that even though Lua can fake Object Oriented concepts, it is not built as an Object Oriented language, and should not be used primarily as one. If you want a fully OO scripting language, use python instead.
Now if you Really want to do it the other way, and considered that the other alternatives do not work for you, then what I would recommend, is that you keep the Lua object as a coroutine, this will allow you to:
Keep a representation of the object
in C++ (the lua_State *)
Have multiple individual instances of the same "object type"
Lua takes care of the cleanup
However, the downsides are:
All functions that act on an "object"
need to do so through the lua API
There is no easy/fast way to recognize different lua types (you
could use a metatable)
Implementation is quite cumbersome, and hard to decypher.
EDIT:
Here is how you could expose the interface to an object in a script, Each object instance would be running a new lua_State, and run its script individually, thus allowing for your "Object member data" to just be globals inside the script instance. Implementing the API for the object's methods would go like this:
int move(lua_State * L)
{
int idx = lua_getglobal(L, "this");
assert(!lua_isnull(-1));
AIObject * obj = static_cast<AIObject *>(lua_touserdata(L, -1));
lua_pop(1);
//Pop the other parameters
obj->move(/*params*/);
}
You can bind any C function you want to Lua and call it from there. You can define in this function what you expect the contract is between your script and your C++ code. For example, the following would kind of do what you want. You'll need to add meta table information to your Lua tables so you can distinguish different Lua object types.
int lua_AddBankAccount(lua_State* L, int pos)
{
// Assume you've created metadata for your Lua objects.
if (IsAccount(L, pos))
{
// process your 'Account' Lua instance.
}
else
{
// error - tried to add a non-Account.
}
}
You can take this further with SWIG to bind any arbitrary C method, but it's basically the same.