OOP in Lua From C - c++

I would like to implement Object Orientated Programming in my lua interpreter, I understand that I can return a lua table from a C Function. And I would like the table that is returned to be full of C functions.
player = getClosestPlayer();
player.walkTo();
where both getClosestPlayer() and walkTo() are C functions.
From the C function for walkTo(), how do I differentiate between object types?
I would prefer every object to have a gid that I can use to identify it (player.gid) but how do I access that gid from the c function?
In other words, what is the equivalent of self.gid from C code?
int l_playerWalkTo(lua_State* functionState){
int gid = // self.gid?
// do something with gid
}
One way I could do this is to upvalue every single function in the table, but is there a more elegant way to do it?

Many thanks to macroland for his answer, I just though I would clear up what he has said.
This lua wrapper can be used to implement c++ classes into Lua:
https://bitbucket.org/alexames/luawrapper/overview
A great example of the usage of this library can be found here:
https://bitbucket.org/alexames/luawrapperexample/src/
Here is the code (taken straight from the example site)
Lua:
alicesaccount = BankAccount.new("Alice", 100)
alicesaccount:deposit(20);
alicesaccount:deposit(30);
alicesaccount:deposit(40);
c++:
BankAccount* BankAccount_new(lua_State *L)
{
const char* owner = luaL_checkstring(L, 1);
float balance = luaL_checknumber(L, 2);
return new BankAccount(owner, balance);
}
int BankAccount_deposit(lua_State *L)
{
BankAccount* account = luaW_check<BankAccount>(L, 1);
float amount = luaL_checknumber(L, 2);
account->deposit(amount);
return 0;
}
static luaL_Reg BankAccount_table[] =
{
{ NULL, NULL }
};
static luaL_Reg BankAccount_metatable[] =
{
{ "deposit", BankAccount_deposit },
{ NULL, NULL }
};
int luaopen_BankAccount(lua_State* L)
{
luaW_register<BankAccount>(L,
"BankAccount",
BankAccount_table,
BankAccount_metatable,
BankAccount_new // If your class has a default constructor you can omit this argument,
// LuaWrapper will generate a default allocator for you.
);
return 1;
}
As you can see, Using this method the first argument is an instance of the object

I had the similar problem and the way I resolved is:
1) Create an interface class in C++ with abstract methods
class LuaInterfaceOOP
{
public:
LuaInterfaceOOP(){}
virtual CObject* clone(void) const=0;
virtual wxString type(void)=0;
virtual wxString ToString(void)=0;
wxString GetType()return this->type();
wxString GetToString() return this->ToString();
virtual ~CObject(){}
};
2) Any class that you want to expose to Lua should implement this to be consistent.
class MyClass: public LuaInterfaceOOP
{
public:
wxString type() { return "MyClass";}
wxString ToString();
};
3) When you write a wrapper for this class make sure
int MyClass_toString(lua_State* L)
{
MyClass* mc= luaW_check<MyClass>(L, 1);
const char* str=mc->ToString().c_str();
lua_pushstring(L, str);
return 1;
}
int MyClass_type(lua_State* L)
{
lua_pushstring(L,"MyClass");
return 1;
}
4) Overload the type function provided by Lua, for you the important part will be:
case LUA_TUSERDATA:
{
wxString str1;
if(lua_getmetatable(L,idx)) // Stk: Userdata Table
{
lua_getfield(L,-1,"type"); // Stk: Userdata Table function
if(!lua_pcall(L,0,1,0)) // Stk: Userdata Table string
{
str1<<lua_tostring(L,-1);
wxReturnStr<<str1;
lua_pop(L,2);// Stk: Userdata
}
else //stk: Userdata table
{
lua_pop(L,1);
wxReturnStr<<"userdata"; //stk: Userdata
}
}else wxReturnStr<<"userdata";
break;
}
EDIT 1: Adding code to wrap C++ funcs to Lua
static luaL_Reg MyClass_table[] = {
{ NULL, NULL }
};
static luaL_Reg Myclass_metatable[] = {
{"type", Myclass_type},
{"__tostring", Myclass_toString},
{ NULL, NULL }
};
Finally,
static int luaopen_MyClass(lua_State* L)
{
luaW_register<MyClass>(L, "MyClass", MyClass_table, MyClass_metatable, MyClass_new);
return 1;
}
Now in Lua you can use an expression such as if(type(aclass)=="MyClass")
I am not sure if these steps are the best way, but so far it worked.

Related

c ++ Class Method Pointer as Function Argument

I am trying to create a dynamic function pointer that points to some methods all the methods I want to save on the array return a bool and have an uint32_t parameter. The functions are Service functions. These are intended to be dynamic, so when a class is started, the constructor links the service function from the object to be called from outside the object.
With the code below I am getting the following error:
Build error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function.
I have no clue what to do to overcome this problem, any idea would be greatly appreciated, thanks!
//File 1
typedef bool (*ServiceFunctionsType)(uint32_t);
//File 2
#include "File1.hpp"
extern uint8_t ServiceFunctions_size;
extern ServiceFunctionsType *ServiceFunctions;
void Service_Functions_Setup();
bool SetPtr(ServiceFunctionsType a);
void ClearPtr(uint8_t id);
//File 3
#include "File1.hpp"
ServiceFunctionsType *ServiceFunctions;
uint8_t ServiceFunctions_size = 0;
//File 4
#include "File2.hpp"
#include <stdlib.h>
void Service_Functions_Setup()
{
ServiceFunctions = NULL;
if(SERVICE_FUNCTION_POINTER_START_SIZE != 0)
{
ServiceFunctions_size = SERVICE_FUNCTION_POINTER_START_SIZE;
ServiceFunctions = (ServiceFunctionsType*)malloc(sizeof(ServiceFunctionsType)*SERVICE_FUNCTION_POINTER_START_SIZE);
for(uint8_t i = 0; i < SERVICE_FUNCTION_POINTER_START_SIZE; i++)
{
ServiceFunctions[i] = NULL;
}
}
}
uint8_t SetServiceFunctionPointer(ServiceFunctionsType a, bool _realloc)
{
if( ServiceFunctions == NULL )
{
ServiceFunctions = (ServiceFunctionsType*)malloc(sizeof(ServiceFunctionsType));
ServiceFunctions[0] = a;
return 0;
}
for(uint8_t i = 0; i < ServiceFunctions_size; i++)
{
if( ServiceFunctions[i] == NULL )
{
ServiceFunctions[i] = a;
return i;
}
}
if(_realloc)
{
ServiceFunctions_size++;
ServiceFunctions = (ServiceFunctionsType*)realloc(ServiceFunctions,sizeof(ServiceFunctionsType)*ServiceFunctions_size);
ServiceFunctions[ServiceFunctions_size - 1] = a;
return ServiceFunctions_size - 1;
}
return INVALID_SERVICE_FUNCTION_POINTER;
}
void ClearServiceFunctionPointer(uint8_t id)
{
ServiceFunctions[id] = NULL;
}
//File 5
class MonoStepSequencer
{
public:
MonoStepSequencer();
~MonoStepSequencer();
uint8_t ServicePointerID;
bool Service(uint32_t time);
private:
};
//File 6
#include "File2.hpp"
MonoStepSequencer::MonoStepSequencer()
{
ServicePointerID = SetServiceFunctionPointer(&this -> Service);
}
//This is the function to be called with a pointer
bool MonoStepSequencer::Service(uint32_t time)
{
//Some Code
}
You can try, to use lambdas. Create method like
std::function<void()> getService()
Where inside you can use:
return [this](){
Service();
};
Also if your methods should use arguments, you can use this method, but add arguments into return value and lambda.
One more, you can create lambda outside of class methods, like:
[&object]()
{
object.Service();
}
In this way, better to use std::shared_ptr to guŠ°rantee that object exists, when lambda called.
this -> Service is an unqualified or parenthesized non-static member function
You probably meant :: instead of -> Also, you need a type on the left, not a variable.
Also, please don't put spaces around ->. That makes it look like you're specifying a trailing return type or something.

Emulating std::bind in C

I'm using std::bind to provide a callback while abstracting some logic by binding some parameters first. i.e.
void start() {
int secret_id = 43534;
//Bind the secret_id to the callback function object
std::function<void(std::string)> cb = std::bind(&callback, secret_id, std::placeholders::_1);
do_action(cb);
}
void do_action(std::function<void(std::string)> cb) {
std::string result = "hello world";
//Do some things...
//Call the callback
cb(result);
}
void callback(int secret_id, std::string result) {
//Callback can now do something with the result and secret_id
}
So in the above example, the do_action does not need to know about the secret_id and other functions can reuse it without having a secret_id of their own. This is especially useful when do_action is some kind of asynchronous operation.
My question is, is there a way to bind parameter values to function pointers using only C?
If not by emulating std::bind then is there another way to pass data from first() to callback() without complicating the neutral do_action()?
No. C doesn't allow you to do that directly.
In C the standard way to handle callbacks is using context pointers:
void register_callback(void (*cback)(void *context, int data),
void *context);
this means that you will pass a function that will accept a void * in addition to the normal parameters that the callback should handle (in the above case an integer) and you will also pass a void * that you want to be passed back.
This void * normally points to a struct that will contain all the extra parameters or data you need in the callback and using this approach the library doesn't depend on what this context is. If the callback doesn't need any context you just pass a NULL pointer as context and ignore the first parameter when being called from the library.
Something that is kind of hackish and formally unsafe but it's sometimes done is that if the context is a simple data that fits the size of a void * (e.g. an integer) and if your environment is not going to have problems with it you can trick the library by passing a fake void * that is just an integer and you convert it back to an integer when being called from the library (this saves the caller from allocating the context and managing its lifetime).
On how to how to trick the language to avoid this limitation (still remaining in the land of portable C) I can think some hack:
First we allocate a pool of two-arguments callbacks and context data
void (*cbf[6])(int, int);
int ctx[6];
then we write (or macro-generate) functions that we wish to register and that will call the two-arguments versions.
void call_with_0(int x) { cbf[0](ctx[0], x); }
void call_with_1(int x) { cbf[1](ctx[1], x); }
void call_with_2(int x) { cbf[2](ctx[2], x); }
void call_with_3(int x) { cbf[3](ctx[3], x); }
void call_with_4(int x) { cbf[4](ctx[4], x); }
void call_with_5(int x) { cbf[5](ctx[5], x); }
We also store them in a pool where they're allocated and deallocated:
int first_free_cback = 0;
int next_free_cback[6] = {1, 2, 3, 4, 5, -1};
void (*cbacks[6])(int) = { call_with_0,
call_with_1,
call_with_2,
call_with_3,
call_with_4,
call_with_5 };
Then to bind the first parameter we can do something like
void (*bind(void (*g)(int, int), int v0))(int)
{
if (first_free_cback == -1) return NULL;
int i = first_free_cback;
first_free_cback = next_free_cback[i];
cbf[i] = g; ctx[i] = v0;
return cbacks[i];
}
but bound functions must also be explicitly deallocated
int deallocate_bound_cback(void (*f)(int))
{
for (int i=0; i<6; i++) {
if (f == cbacks[i]) {
next_free_cback[i] = first_free_cback;
first_free_cback = i;
return 1;
}
}
return 0;
}
As 6502 explained, it is not possible to do this in portable C without some kind of context argument being passed to the callback, even if it doesn't name secret_id directly. However, there are libraries such as Bruno Haible's trampoline that enable creation of C functions with additional information (closures) through non-portable means. These libraries do their magic by invoking assembly or compiler extensions, but they are ported to many popular platforms; if they support architectures you care about, they work fine.
Taken from the web, here is an example of code that trampoline enables is this higher-order function that takes parameters a, b, and c (analogous to your secret_id, and returns a function of exactly one parameter x that calculates a*x^2 + b*x + c:
#include <trampoline.h>
static struct quadratic_saved_args {
double a;
double b;
double c;
} *quadratic_saved_args;
static double quadratic_helper(double x) {
double a, b, c;
a = quadratic_saved_args->a;
b = quadratic_saved_args->b;
c = quadratic_saved_args->c;
return a*x*x + b*x + c;
}
double (*quadratic(double a, double b, double c))(double) {
struct quadratic_saved_args *args;
args = malloc(sizeof(*args));
args->a = a;
args->b = b;
args->c = c;
return alloc_trampoline(quadratic_helper, &quadratic_saved_args, args);
}
int main() {
double (*f)(double);
f = quadratic(1, -79, 1601);
printf("%g\n", f(42));
free(trampoline_data(f));
free_trampoline(f);
return 0;
}
The short answer is no.
The only thing you can do is declare another function that has the secret_id built into it. If you're using C99 or newer you can make it an inline function to at least limit the function call overhead, although a newer compiler may do that by itself anyway.
To be frank though, that is all std::bind is doing, as it is returning a templated struct, std::bind simply declares a new functor that has secret_id built into it.
An opaque type and keeping secret in a source should do it:
#include <stdio.h>
// Secret.h
typedef struct TagSecret Secret;
typedef void (*SecretFunction)(Secret*, const char* visible);
void secret_call(Secret*, const char* visible);
// Public.c
void public_action(Secret* secret, const char* visible) {
printf("%s\n", visible);
secret_call(secret, visible);
}
// Secret.c
struct TagSecret {
int id;
};
void secret_call(Secret* secret, const char* visible) {
printf("%i\n", secret->id);
}
void start() {
Secret secret = { 43534 };
public_action(&secret, "Hello World");
}
int main() {
start();
return 0;
}
(The above does not address registering callback functions)

C++ container classes

currently I switch from Java to C++ and this is giving me a hard time (but lots of new experience ^^). I'm writing some data-transfer-objects which contain configurations for my program. I've written some classes and now I want to have a class which behaves like a container.
Here's a header for the container:
class MyContainer{
public:
MyContainer();
virtual ~MyContainer();
Config getConfig(TypeEnum type) {
switch (type) {
case ATYPE:
return config_a;
case BTYPE:
return config_b;
default:
break;
}
}
ConfigA config_a;
ConfigB config_b;
};
The configs have some data in it and are derived from another config-file.
And here is the C++-Source:
MyContainer::MyContainer(){
ConfigA config_a(int c = 1);
ConfigB config_b(double b = 2.1);
this->config_a = config_a;
this->config_b = config_b;
}
There are several problems I think. But the main question for me is:
How can I get those configs in this container to share it to other modules of my program? I have tried to make config_a to a pointer but I always get error-messages that these types won't match.
this->config_a = &config_a; //If ConfigA config_a; was ConfigA *config_a; instead
If you have another minute for me then please tell me if the getConfig-Method could work like this.
And if there's another topic for this then please share. Thanks.
If you write ConfigA configA in your header, the configA is automatically allocated during the allocation of the container class. So you don't have to initialize it like following:
ConfigA config_a(1);
this->config_a = config_a;
Instead, you can just do the following:
this->config_a->value = 1;
There is no need to write:
ConfigA config_a(int c = 1);
In short words, the mentioned int c = 1 is an operation, which:
allocates space on heap for temporary variable c (this may be done when entering the method as well)
assigns value to it, which has side effect of returning the right-hand-side value
the returned right-hand-side value is applied to the ConfigA constructor.
To understand this, try the following:
int a, b, c;
c = (a = 2) + (b = 8);
printf("a = %d, b = %d, c = %d\n", a, b, c);
If you want to pass the configs to another modules, you can choose one of the following solutions:
a) Accept the configs as references (the config classes have to derive from the same base class):
ConfigA & configA = dynamic_cast<ConfigA &>(container.get_config(ATYPE));
In this case, container shall return the configs in the following way:
return this->configA;
But the header shall be modified:
Config & getConfig(TypeEnum type) { (...)
b) Accept the configs as pointers (same as above)
ConfigA * configA = dynamic_cast<ConfigA *>(container.get_config(ATYPE));
In this case, container shall return the configs in the following way:
return &(this->configA);
Finally, this is the way I would do it:
class ConfigA
{
private:
int i;
public:
int GetI() const { return i; }
void SetI(int newI) { i = newI; }
};
class ConfigB
{
private:
float f;
public:
float GetF() const { return f; }
void SetF(float newF) { f = newF; }
};
class Config
{
private:
ConfigA configA;
ConfigB configB;
public:
ConfigA & GetConfigA() { return configA; }
ConfigB & GetConfigB() { return configB; }
};
class AppContext
{
private:
Config config;
public:
Config & GetConfig() { return config; }
};
// Somewhere in the code
Config & config = context.GetConfig();
ConfigA & configA = config.GetConfigA();
configA.SetI(44);
The const-correctness is also worth mentioning, but we'll leave it as an exercise for the OP ;)
Your code:
ConfigA config_a(int c = 1);
Means a function prototype that returns ConfigA and takes an int with a default value of 1.
But if you seperate the int declaration from the expression, it will change to something else:
int c;
ConfigA config_a(c = 1); // This is construction of a ConfigA object
I would write the constructor like this:
MyContainer::MyContainer(int c = 1, double d = 2.1)
: config_a (c), config_b (d) // Construct the members in the intialization line
{
}
If you want to share a pointer to these members, return a pointer like this:
ConfigA * MyContainer::GetConfigA(){return &config_a;}
ConfigB * MyContainer::GetConfigB(){return &config_b;}
But if you want to work with pointer members:
MyContainer::MyContainer(int c = 1, double d = 2.1)
: pConfig_a (new ConfigA (c)), pConfig_b (new ConfigB (d))
{
}
ConfigA * MyContainer::GetConfigA(){return pConfig_a;}
ConfigB * MyContainer::GetConfigB(){return pConfig_b;}
MyContainer::~MyContainer()
{
delete pConfig_a;
delete pConfig_b;
}

VC++ "Re-use" a function?

How can I re-use a function?
Okay lets say I have this "main" function below:
bool A = false;
bool B = true;
void MainFunction(bool Whatever) {
if(!Whatever) {
A = true;
if(A) {
B = false;
} else if(!A) {
B = true;
}
}
}
Now I want to make a new function using the MainFunction, something like this:
MainFunction ANewFunction(false);
MainFunction AnotherNewFunction(true);
Obviously that won't work, so is there any way to "re-use" a function as a different function?
You're welcome to have one function call another. For example:
void ANewFunction() {
MainFunction(false);
}
void AnotherNewFunction() {
MainFunction(true);
}
You can even get fancy:
#include <functional>
auto ANewFunction = std::bind(&MainFunction, false);
auto AnotherNewFunction = std::bind(&MainFunction, true);
Either way, you can call ANewFunction or AnotherNewFunction, and MainFunction will get called with the given argument. (In the latter case, they're not really functions anymore. They're called function objects, or functors, but you cal still call them just like ordinary functions: ANewFunction().)
You can't "re-use" functions, at least not in the way I understand your question.
But you can create a new function that calls the original function and then does some additional work of its own. For example:
void PrevFunction(int one)
{
int i = one;
// do whatever
}
void NewFunction(int one)
{
PrevFunction(one);
// do new stuff
// ...
}
You could also define a class, and then use inheritance and virtual functions to modify the behavior of a particular set of functions from the base class.
typedef int (*function_t)(int); // new type - defines function type - address of function
// your function, PrevFunction is simply variable holding address of the function:
int PrevFunction(int one) { return one; }
// new variable of type function_t initialized by PrevFunction address:
function_t NewFunction = PrevFunction;
//And finally we can use either PrevFunction or NewFunction - they point to the same function body:
int a = PrevFunction(1); // a == 1
int b = NewFunction(2); // a == 2
Simply call MainFunction from your other function?
void ANewFunction()
{
MainFunction(false);
}
void AnotherNewFunction()
{
MainFunction(true);
}
If your question is how do you make AnotherNewFunction refer to a different A and B than ANewFunction, the answer is you can't, at least not without help from MainFunction. You can, however, update MainFunction:
void MainFunction(bool Whatever, bool& A, bool& B) {
if(!Whatever) {
A = true;
if(A) {
B = false;
} else if(!A) {
B = true;
}
}
}
bool A1 = false;
bool B1 = true;
void ANewFunction()
{
MainFunction(false, A1, B1);
}
bool A2 = false;
bool B2 = true;
void AnotherNewFunction()
{
MainFunction(true, A2, B2);
}
Another new-fangled solution, using lambda's:
auto ANewFunction = [](){ MainFunction(false); }
auto AnotherNewFunction = [](){ MainFunction(true); }

QtScript -- script-side callback through C++-side implementation

The solution may be simple. Then again it may not be possible.
I have the base callback class:
class CFCallback {
int command_;
int transfer_rate_;
public:
CFCallback(int command, int transfer_rate = 0) {
command_ = command; transfer_rate_ = transfer_rate; }
virtual ~CFCallback() {}
virtual void operator()(void *data) = 0;
int GetCommand() { return command_; }
int GetTransferRate() { return transfer_rate_; }
};
And here's one example of deriving from CFCallback:
void CFPacketVersion::InitiateVersion() {
class InitiateVersionCB : public CFCallback {
CFPacketVersion *visitor_;
public:
InitiateVersionCB(CFPacketVersion *v, int command) :
CFCallback(command) {
visitor_ = v;
}
void operator()(void *data) {
Packet *pkt = (Packet *)data;
unsigned char *pkt_data = pkt->GetData();
std::string version = "";
for(unsigned int i = 0; i < pkt->GetDataLength(); i++ )
version+= pkt_data[i];
delete []pkt_data;
boost::regex rex("CFA(.*?):h(.*?),v(.*?)$");
boost::smatch what;
if( boost::regex_match(version, what, rex) ) {
if(visitor_->GetModel()->GetName() != what[1].str() )
LCDInfo("Crystalfontz: Model mismatch");
visitor_->SetHardwareVersion(what[2]);
visitor_->SetFirmwareVersion(what[3]);
}
}
};
GetVersion(new InitiateVersionCB(this, 1));
}
GetVersion(CFCallback *) is provided to the script engine.
I want to be able to do the same thing as seen in InitiateVersion, but on the javascript side of things. Is that possible?
I know I need to register meta type info for CFCallback. But I don't know if it's possible to use a pointer to a CFCallback. What I tried initially didn't work.
Also, seeing as CFCallback is a functor, I'm not sure how I translate that over to javascript. I imagine I can make CFCallback a QObject and provide a signal emitted from operator(). If you have any tips, please share.
I'm afraid it won't work the way you've set it up.
If you want to be able to create the callback in javascript, you need a QObject with an accessible GetVersion(QScriptValue) which the script will the use to pass a script-based implementation of the callback. Note, though, that the callback will not be able to work with untyped (void*) data - you need to pass either a valid QtScript object or QObject with a proper interface (like the Packet one in your example!)
You could then wrap it up like this:
QtScript:
function mycb(packet) {
var pkt_data = packet.getData(); // pkt_data is probably a String or custom object with proper interface so to simplify things get the version as string
var version = pkt_data.toString();
pkt_data.release(); // to simulate delete [] pkt_data; this is part of custom interface
// proceed further with the regex checks
}
GetVersion(mycb); // implies that you define the GetVersion() as a property of the global object
C++:
QScriptValue getVersion(QScriptContext *ctx, QScriptEngine *engine)
{
void *data = ...;
Packet pkt_data = wrapPacketData(data);
// Packet is interface registered with QtScript or inherits QObject
// it has methods getData(), toString() and release()
QScriptValueList args;
QScriptValue pkt_data_param = engine->newQObject(&pkt_data);
args << pkt_data_param;
QScriptValue cb = ctx->argument(0);
Q_ASSERT(cb.isFunction()); // we expect a function object!
cb.call(QScriptValue(), args);
}
QScriptValue getVersionFun = engine->newFunction(getVersion);
engine->globalObject().setProperty(QLatin1String("GetVersion"), getVersionFun);