Extract userdata from table,using lua c API - c++

I use lua c api to loop the variables in a table, like this
lua script:
array = {0,1,2,3}
lua c api
lua_getglobal(l, "array");
if(lua_isnil(l, -1)) {
}
lua_pushnil(l);
while(lua_next(l, -2)) {
int value=(int)lua_tonumber(l, -1);
printf("%d \n",value);
lua_pop(l, 1);
}
and I can get the result
0
1
2
3
Then I want to put some userdata objs into the table
and then loop them in the c api
lua script
foo0 = Foo.new("fred0")
foo1 = Foo.new("fred0")
foo2 = Foo.new("fred0")
foo3 = Foo.new("fred0")
array = {foo0,foo1,foo2,foo3}
lua c api
extern "C"
{
#include "lua.h"
#include "lauxlib.h"
#include "lualib.h"
}
#include <iostream>
#include <sstream>
#include <vector>
class Foo
{
public:
Foo(const std::string & name) : name(name)
{
std::cout << "Foo is born" << std::endl;
}
std::string Add(int a, int b)
{
std::stringstream ss;
ss << name << ": " << a << " + " << b << " = " << (a+b);
return ss.str();
}
~Foo()
{
std::cout << "Foo is gone" << std::endl;
}
std::string name;
};
int l_Foo_constructor(lua_State * l)
{
const char * name = luaL_checkstring(l, 1);
Foo ** udata = (Foo **)lua_newuserdata(l, sizeof(Foo *));
*udata = new Foo(name);
luaL_getmetatable(l, "luaL_Foo");
lua_setmetatable(l, -2);
return 1;
}
Foo * l_CheckFoo(lua_State * l, int n)
{
return *(Foo **)luaL_checkudata(l, n, "luaL_Foo");
}
int l_Foo_add(lua_State * l)
{
return 1;
}
int l_Foo_destructor(lua_State * l)
{
Foo * foo = l_CheckFoo(l, 1);
delete foo;
return 0;
}
void RegisterFoo(lua_State * l)
{
luaL_Reg sFooRegs[] =
{
{ "new", l_Foo_constructor },
{ "add", l_Foo_add },
{ "__gc", l_Foo_destructor },
{ NULL, NULL }
};
luaL_newmetatable(l, "luaL_Foo");
luaL_register(l, NULL, sFooRegs);
lua_pushvalue(l, -1);
lua_setfield(l, -1, "__index");
lua_setglobal(l, "Foo");
}
int main()
{
lua_State * l = luaL_newstate();
luaL_openlibs(l);
RegisterFoo(l);
int erred = luaL_dofile(l,"/Volumes/Work/CODE/Test/testStatic/testStatic/kami.txt");
if(erred)
std::cout << "Lua error: " << luaL_checkstring(l, -1) << std::endl;
lua_getglobal(l, "array");
if(lua_isnil(l, -1)) {
//return std::vector();
}
lua_pushnil(l);
std::vector<Foo *> v;
while(lua_next(l, -2)) {
Foo * foo = l_CheckFoo(l, -1);//this line do not work
//
//
//
//
//I don't know how to do it here.
//
//
//
//
//v.push_back(foo);
lua_pop(l, 1);
}
// for (Foo* theValue:v)
// {
// printf("==>%s",theValue->name.c_str());
// }
lua_close(l);
return 0;
}
how to extract userdata from a table?
please help me,thank you.

finally I soved it by myself
l_CheckFoo(l, -1);
should be
lua_touserdata(l, -1);
void * hehe=lua_touserdata(l, -1);
Foo ** haha=(Foo **)hehe;
Foo *f=*haha;
printf("%s \n",f->name.c_str());

Related

How to make 2 functions work instead of only 1

I have 2 void functions and a main func.
But since first function has while(true) it works always and due to that second is not working. How to make it work all together at the same time?
void shoot()
{
*(DWORD*)(val.gameModule + offsets.ForceAttack, 5);
Sleep(5000);
*(DWORD*)(val.gameModule + offsets.ForceAttack, 4);
}
void bunny()
{
val.gameModule = (DWORD)GetModuleHandle("client_panorama.dll");
std::cout << (GetModuleHandle("client_panorama.dll")) << std::endl;;
val.localPlayer = *(DWORD*)(val.gameModule + offsets.lplayer);
while (true)
{
if (bunnyON == 1);
else
return;
val.flag = *(BYTE*)(val.localPlayer + offsets.flags);
if (isMoving())
if (GetAsyncKeyState(VK_SPACE) && val.flag & (1 << 0))
* (DWORD*)(val.gameModule + offsets.jump) = 6;
}
}
int main()
{
bunny();
shoot();
}
`
Try to do this, and check if this is what you need:
#include <thread>
void shoot()
{
*(DWORD*)(val.gameModule + offsets.ForceAttack, 5);
Sleep(5000);
*(DWORD*)(val.gameModule + offsets.ForceAttack, 4);
}
void bunny()
{
val.gameModule = (DWORD)GetModuleHandle("client_panorama.dll");
std::cout << (GetModuleHandle("client_panorama.dll")) << std::endl;;
val.localPlayer = *(DWORD*)(val.gameModule + offsets.lplayer);
while (true)
{
if (bunnyON == 1);
else
return;
val.flag = *(BYTE*)(val.localPlayer + offsets.flags);
if (isMoving())
if (GetAsyncKeyState(VK_SPACE) && val.flag & (1 << 0))
* (DWORD*)(val.gameModule + offsets.jump) = 6;
}
}
int main()
{
std::thread t1(bunny);
std::thread t2(shoot);
t1.join();
t2.join();
return 0;
}

C++ Error when threading, std::invoke:

Okay, so these are my errors.
std::invoke: no matching overloaded function found
// and
Failed to specialize function template 'unkown-type std::invoke("Callable &&,_Types &&...) noexcept()'
I really need your guys help. Im pretty new to C++, so I would like if you gave me examples on how to do it. Not only explain.
And this is my code:
#include <iostream>
#include <thread>
#include <stdio.h>
#include <Windows.h>
#include <string>
using namespace std;
void SetColor(int ForgC);
void Navigation();
void Switch(int index);
void UpdateMenu();
const int IWAL = 1;
const int ITRI = 0;
int M_Index = 0;
int Changes = 0;
bool Name1 = false;
bool Name2 = false;
string bools[2] = { "[OFF]", "[ON]" };
void Navigation()
{
for (;;)
{
for (int i = 2; i < 180; i++)
{
if (GetAsyncKeyState(i) & 0x8000)
{
switch (i)
{
case 38:
if (M_Index < 2)
M_Index++;
Changes++;
break;
case 40:
if (M_Index > 0)
M_Index--;
Changes++;
break;
case 37:
Switch(M_Index);
Changes++;
break;
case 39:
Switch(M_Index);
Changes++;
break;
}
Sleep(200);
}
}
}
}
void Switch(int index)
{
if (index == IWAL)
{
Name1 = !Name1;
}
else if (index == ITRI)
{
Name2 = !Name2;
}
}
void UpdateMenu()
{
int temp = -1;
for (;;)
{
if (temp != Changes)
{
temp = Changes;
system("cls");
SetColor(15);
cout << ">> Krizzo's Menu <<" << endl;
cout << "___________________" << endl << endl;
if (M_Index == IWAL)
{
SetColor(10);
cout << " Name1\t=\t" << bools[Name1] << endl;
}
else
{
SetColor(15);
cout << " Name1\t=\t" << bools[Name1] << endl;
}
if (M_Index == ITRI)
{
SetColor(10);
cout << " Name2\t=\t" << bools[Name2] << endl;
}
else
{
SetColor(15);
cout << " Name2\t=\t" << bools[Name2] << endl;
}
}
}
}
void SetColor(int ForgC)
{
WORD wColor;
//We will need this handle to get the current background attribute
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
//We use csbi for the wAttributes word.
if (GetConsoleScreenBufferInfo(hStdOut, &csbi))
{
//Mask out all but the background attribute, and add in the foreground color
wColor = (csbi.wAttributes & 0xF0) + (ForgC & 0x0F);
SetConsoleTextAttribute(hStdOut, wColor);
}
return;
}
int main(int argc, char** argv) {
std::thread t1(Navigation);
std::thread t2(Switch);
std::thread t3(UpdateMenu);
std::thread t4(SetColor);
t1.join();
t2.join();
t3.join();
t4.join();
return 0;
}
Your Switch and SetColor functions take a parameter. You have to pass this parameter to the thread constructor. Example:
int addOne(int x)
{
return x + 1;
}
int main()
{
std::thread t1(addOne, 5);
t1.join();
}
When dealing with reference parameters, you have to wrap the parameter in a std::ref() call:
void addOne(int& x)
{
x += 1;
}
int main()
{
int a = 42;
std::thread t1(addOne, std::ref(a));
t1.join();
}
Lastly, when you want to run a member function of a class on a seperate thread, you have to pass the this pointer, as the thread has to know which instance the member function is called on.
class X
{
void doSomething()
{
std::thread t1(X::expensiveCalculations, this);
//do something else
t1.join();
}
void expensiveCalculations()
{
}
};
int main()
{
X x;
x.doSomething();
}

ZeroMQ PUB/SUB bind subscriber

I'm studying ZeroMQ with myself.
I tested PUB as a server(bind), SUB as a client(connect) and worked fine. Opposite (PUB as a client(connect), SUB as a server(bind)) also works fine.
When I connect a another SUB socket as client something goes wrong without any exception or errors.
here's my example code.
#include <zmq.hpp>
#include <string>
#include <iostream>
#include <unistd.h>
#include <thread>
class ZMQSock
{
public:
ZMQSock(const char* addr)
{
if (addr != NULL)
{
mctx = new zmq::context_t(1);
mszAddr = new char[strlen(addr) + 1];
snprintf(mszAddr, strlen(addr) + 1, "%s", addr);
}
}
virtual ~ZMQSock()
{
if (msock != nullptr)
delete msock;
if (mctx != nullptr)
delete mctx;
if (mszAddr != nullptr)
delete [] mszAddr;
}
int zbind()
{
if (msock != nullptr)
msock->bind(mszAddr);
else return -1;
return 0;
}
int zconnect()
{
if (msock != nullptr)
msock->connect(mszAddr);
else return -1;
return 0;
}
void start()
{
if (mbthread != false)
return ;
mbthread = true;
mhthread = std::thread(std::bind(&ZMQSock::run, this));
}
virtual void stop()
{
if (mbthread == false)
return ;
mbthread = false;
if (mhthread.joinable())
mhthread.join();
}
virtual void run() = 0;
protected:
char* mszAddr{nullptr};
zmq::context_t* mctx{nullptr};
zmq::socket_t* msock{nullptr};
bool mbthread{false};
std::thread mhthread;
};
class ZPublisher : public ZMQSock
{
public:
ZPublisher(const char* addr) : ZMQSock(addr)
{
if (msock == nullptr)
{
msock = new zmq::socket_t(*mctx, ZMQ_PUB);
}
}
virtual ~ZPublisher()
{
}
bool zsend(const char* data, const unsigned int length, bool sendmore=false)
{
zmq::message_t msg(length);
memcpy(msg.data(), data, length);
if (sendmore)
return msock->send(msg, ZMQ_SNDMORE);
return msock->send(msg);
}
void run()
{
if (mszAddr == nullptr)
return ;
if (strlen(mszAddr) < 6)
return ;
const char* fdelim = "1";
const char* first = "it sends to first. two can not recv this sentence!\0";
const char* sdelim = "2";
const char* second = "it sends to second. one can not recv this sentence!\0";
while (mbthread)
{
zsend(fdelim, 1, true);
zsend(first, strlen(first));
zsend(sdelim, 1, true);
zsend(second, strlen(second));
usleep(1000 * 1000);
}
}
};
class ZSubscriber : public ZMQSock
{
public:
ZSubscriber(const char* addr) : ZMQSock(addr)
{
if (msock == nullptr)
{
msock = new zmq::socket_t(*mctx, ZMQ_SUB);
}
}
virtual ~ZSubscriber()
{
}
void setScriberDelim(const char* delim, const int length)
{
msock->setsockopt(ZMQ_SUBSCRIBE, delim, length);
mdelim = std::string(delim, length);
}
std::string zrecv()
{
zmq::message_t msg;
msock->recv(&msg);
return std::string(static_cast<char*>(msg.data()), msg.size());
}
void run()
{
if (mszAddr == nullptr)
return ;
if (strlen(mszAddr) < 6)
return ;
while (mbthread)
{
std::cout << "MY DELIM IS [" << mdelim << "] - MSG : ";
std::cout << zrecv() << std::endl;
usleep(1000 * 1000);
}
}
private:
std::string mdelim;
};
int main ()
{
ZPublisher pub("tcp://localhost:5252");
ZSubscriber sub1("tcp://localhost:5252");
ZSubscriber sub2("tcp://*:5252");
pub.zconnect();
sub1.zconnect();
sub2.zbind();
sub1.setScriberDelim("1", 1);
sub2.setScriberDelim("2", 1);
pub.start();
std::cout << "PUB Server has been started.." << std::endl;
usleep(1000 * 1000);
sub1.start();
std::cout << "SUB1 Start." << std::endl;
sub2.start();
std::cout << "SUB2 Start." << std::endl;
int i = 0;
std::cout << "< Press any key to exit program. >" << std::endl;
std::cin >> i;
std::cout << "SUB1 STOP START" << std::endl;
sub1.stop();
std::cout << "SUB2 STOP START" << std::endl;
sub2.stop();
std::cout << "PUB STOP START" << std::endl;
pub.stop();
std::cout << "ALL DONE" << std::endl;
return 0;
}
What causes this? or Am I using PUB/SUB illegally?
You are connecting a SUB socket to a SUB socket, that is an invalid connection. In your case the PUB should bind and the SUBs should connect.

Is there C/C++ equivalent of eval("function(arg1, arg2)")?

it need a way to call function whose name is stored in a string similar to eval. Can you help?
C++ doesn't have reflection so you must hack it, i. e.:
#include <iostream>
#include <map>
#include <string>
#include <functional>
void foo() { std::cout << "foo()"; }
void boo() { std::cout << "boo()"; }
void too() { std::cout << "too()"; }
void goo() { std::cout << "goo()"; }
int main() {
std::map<std::string, std::function<void()>> functions;
functions["foo"] = foo;
functions["boo"] = boo;
functions["too"] = too;
functions["goo"] = goo;
std::string func;
std::cin >> func;
if (functions.find(func) != functions.end()) {
functions[func]();
}
return 0;
}
There are at least 2 alternatives:
The command pattern.
On windows, you can use GetProcAddress to get a callback by name, and dlopen + dlsym on *nix.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
double eval( string expression );
int main( int argc, char *argv[] )
{
string expression = "";
for ( int i = 1; i < argc; i++ )
{
expression = expression + argv[i];
}
cout << "Expression [ " << expression << " ] = " << endl;
eval( expression );
}
double eval( string expression )
{
string program = "";
program = program + "#include <cmath>\n";
program = program + "#include <iostream>\n";
program = program + "using namespace std;\n";
program = program + "int main()\n";
program = program + "{\n";
program = program + " cout << ";
program = program + expression;
program = program + " << endl;\n";
program = program + "}";
ofstream out( "abc.cpp" );
out << program;
out.close();
system( "g++ -o abc.exe abc.cpp" );
system( "abc" );
}
You could try to adopt an existing scripting engine, expose the functions you like to this and then use this to evaluate your statements. One such enging could be the V8 engine: https://developers.google.com/v8/intro but there are many alternatives and different languages to choose from.
Here are some examples:
Boost Python
V8
LUA
AngelScript
Except using the function map in the program and hack it on the Makefile, you can access it through ELF.
I think this method is better as it did not need to write duplicate code and compile it every time on different machine.
Here is my demo C/C++ equivalent of eval(“function(arg1, arg2)”)
#include<stdio.h>
#include<stdlib.h>
#include<elf.h>
#include<libelf.h>
#include<unistd.h>
#include<fcntl.h>
#include<gelf.h>
#include<string.h>
void my_fun()
{
int a = 19;
printf("my_fun is excute, a is %d \n", a);
}
void my_fun2()
{
printf("my_fun2 is excute\n");
return;
}
void my_fun3()
{
return;
}
void excute_fun(char *program_name, char *function_name)
{
int i, count;
Elf32_Ehdr *ehdr;
GElf_Shdr shdr;
Elf *elf;
Elf_Scn *scn = NULL;
Elf_Data *data;
int flag = 0;
int fd = open(program_name, O_RDONLY);
if(fd < 0) {
perror("open\n");
exit(1);
}
if(elf_version(EV_CURRENT) == EV_NONE) {
perror("elf_version == EV_NONE");
exit(1);
}
elf = elf_begin(fd, ELF_C_READ, (Elf *) NULL);
if(!elf) {
perror("elf error\n");
exit(1);
}
/* Elf32_Off e_shoff; */
/* if ((ehdr = elf32_getehdr(elf)) != 0) { */
/* e_shoff = ehdr->e_shoff; */
/* } */
/* scn = elf_getscn(elf, 0); */
/* printf("e_shoff is %u\n", e_shoff); */
/* scn += e_shoff; */
while ((scn = elf_nextscn(elf, scn)) != NULL) {
gelf_getshdr(scn, &shdr);
if (shdr.sh_type == SHT_SYMTAB) {
/* found a symbol table. */
break;
}
}
data = elf_getdata(scn, NULL);
if(!shdr.sh_entsize)
count = 0;
else
count = shdr.sh_size / shdr.sh_entsize;
for (i = 0; i < count; ++i) {
GElf_Sym sym;
gelf_getsym(data, i, &sym);
char *sym_name = elf_strptr(elf, shdr.sh_link, sym.st_name);
if(sym_name != NULL && sym_name[0] != '_' && sym_name[0] != '\0' && sym_name[0] != ' ' && sym.st_value != 0)
{
/* printf("sym_name is %s\n", sym_name); */
/* printf("%s = %X\n", elf_strptr(elf, shdr.sh_link, sym.st_name), sym.st_value); */
if(!strcmp(sym_name, function_name)) {
void (*fun)(void) = (void*)sym.st_value;
(*fun)();
flag = 1;
}
}
}
if(!flag)
printf("can not find this function\n");
elf_end(elf);
close(fd);
}
int main(int argc, char *argv[])
{
char *input = (char*)malloc(100);
for(;;) {
printf("input function_name to excute: ");
scanf("%s", input);
excute_fun(argv[0], input);
memset(input, 0, sizeof(input));
printf("\n");
}
free(input);
return 0;
}
This implementation is based on Example of Printing the ELF Symbol Table

Why is Lua returning an empty table in this code?

edit:
As I commented before, my problem is I can't create a table in C which uses strings as keys. I made a quick test program which demonstrates the problem I'm having:
Here is the C++ part of it:
#include <lua.hpp>
#include <String.h>
BString
LuaTypeToString(lua_State *L, int index, int type)
{
BString out;
switch (type)
{
case LUA_TSTRING:
{
out << "'" << lua_tostring(L, index) << "'";
break;
}
case LUA_TBOOLEAN:
{
out << (lua_toboolean(L, index) ? "true" : "false");
break;
}
case LUA_TNUMBER:
{
out << (float)lua_tonumber(L, index);
break;
}
default:
{
out << lua_typename(L, type);
break;
}
}
return out;
}
void
DumpLuaTable(lua_State *L, int tableIndex)
{
lua_pushnil(L);
printf("\t{ ");
while (lua_next(L, tableIndex) != 0)
{
BString keyString = lua_tostring(L, -2);
BString valueString;
int type = lua_type(L, -1);
if (type == LUA_TTABLE)
DumpLuaTable(L, lua_gettop(L));
else
valueString = LuaTypeToString(L, -1, type);
printf("%s=%s,",
keyString.String(),
valueString.String());
lua_pop(L, 1);
if (lua_isnumber(L, -1))
{
lua_pop(L, 1);
break;
}
}
printf(" }");
}
void
DumpLuaStack(lua_State *L)
{
printf("DumpLuaStack:\n");
int top = lua_gettop(L);
for (int i = 1; i <= top; i++)
{
int type = lua_type(L, i);
if (type == LUA_TTABLE)
DumpLuaTable(L, i);
else
printf("\t%s ", LuaTypeToString(L, i, type).String());
}
printf("\n");
}
static
int
ReturnTable(lua_State *L)
{
lua_newtable(L);
lua_pushnumber(L, 3.14);
lua_pushstring(L, "1");
lua_settable(L, -3);
DumpLuaStack(L);
return 1;
}
int
main(void)
{
lua_State *L = luaL_newstate();
luaL_openlibs(L);
lua_pushcfunction(L, ReturnTable);
lua_setglobal(L, "ReturnTable");
int status = luaL_dofile(L, "luatest.lua");
if (status)
printf("Status = %d: %s\n", status, lua_tostring(L, -1));
lua_close(L);
return status;
}
And the Lua part of it:
function DumpTable(table)
print("LuaDumpTable")
local out = "\t"
if #table > 0 then
for i, v in ipairs(table) do
out = out .. i .. "=" .. v .. " "
end
print(out)
else
print("\tEmpty table")
end
end
value = ReturnTable()
if (type(value) == "table") then
DumpTable(value)
else
print(type(value))
end
The code as it is works without problem -- the Lua script prints out what you would expect. Change the line which pushes 3.14 to the stack to, say, lua_pushstring(L, "foo"); and all I get is an empty table on the Lua side. Any ideas what I'm doing wrong here?
You're checking the table incorrectly in Lua:
if #table > 0 then
The #table is just telling you that the first unused integer in the table is 0. When you have a string inserted into the table, it doesn't increment the count since it's not part of a continuous array, and you also can't process it with ipairs. Just switch to using pairs and you should see foo:
function DumpTable(table)
print("LuaDumpTable")
local out = "\t"
for i, v in pairs(table) do
out = out .. i .. "=" .. v .. " "
end
print(out)
end
Older note, left as an fyi:
I doubt this would cause the issue, but for API's being called from Lua, you typically want to pop the input off of the stack. So after the lua_tonumber call:
int32 value = lua_tonumber(L, 1);
lua_pop(L, 1);
rgb_color c = ui_color((color_which)value);