Вместо того, чтобы создать объект в lua, как позволить lua напрямую вычислить объект C++ для запуска метода?

Я использую Luabind.

Мое название может быть неясным, я постараюсь объяснить, что хочу спросить.

Мой вопрос:
Как напрямую вызвать метод объекта C++, который может получить доступ к значениям объекта (особенно указателям), а не создавать другой объект в Luabind.

Если вы не знаете, что я спрашиваю, вы можете продолжить чтение.

Например, у меня есть три класса: Main, Test_Stage, Test_Class

Луа создается только в Test_class,

У меня есть переменная x, созданный только для целей тестирования. Он прошел весь путь от Main в Test_Stage в Test_Class их конструктор. Так что оба Test_Class а также Test_Stage иметь глобальное значение, которое мне понадобится, когда я действительно создаю игру.
Более важным является то, что Test_Class содержит указатель Test_Stageтак что я могу делать такие вещи, как create_a_bullet или же create_damage,

Извлеченный из этого урока, я пытался сделать luaobject создано в Test_Class вызвать метод shoot_a_bullet который высветит объект Test_Stage, чтобы напечатать "Runned" << "глобальное значение". И без синтаксической ошибки в C++ IT ничего не печатал. Как я могу это исправить?

Коды здесь (на самом деле у меня были проблемы с работой вперед, в том числе с использованием класса, поэтому "Runned" << x находится в Test_Class, По крайней мере, я могу проверить, будет ли он читать глобальное значение, переданное здесь.)

Редактировать: Просто после нескольких часов бездействия, я подумал о другом решении. Есть ли способ, которым я могу передать указатель, который может быть использован в объекте, который создан в lua, или, возможно, используется в конструкторе?

Коды (вы можете пропустить основной и Test_Stage, если вы пришли для ответа на вопрос:

Основной файл запуска программы:

#include <iostream>
#include "test_stage.h"

using namespace std;

int x;

int main() {

    cin >> x;
    Test_Stage stage = Test_Stage(x);
}

И заголовок Test_Stage:

#ifndef TEST_STAGE_H
#define TEST_STAGE_H
#include <iostream>
class Test_Class;// to avoid circular include error, i used forward referancing
                 // i will include the file in the CPP file
                 // a class Test_Class which define the class is enough in header
using namespace std;

class Test_Stage
{
    public:
        int x;
        Test_Stage(int num);

        void create_bullet(int damage, string name, int x); /*This is currently useless 
            before i have understand how to include each other using foward referance*/
        void create_class(int num);

        Test_Class t_class;

        ~Test_Stage();
    private:

};

#endif

Файл cpp Test_Stage:

#include"test_stage.h"
#include "test_class.h"// and as you see i included both files(i just learned it few secs ago)

Test_Stage::Test_Stage()
{

}

Test_Stage::Test_Stage(int num)
{
    create_class(num);
}

void Test_Stage::create_bullet(int damage, string name, int x)
{
    cout << "created damage: " << damage << "to" << x ;
}

void Test_Stage::create_class(int num)
{
    Test_Class t_class = Test_Class(num, this);
}

Test_Stage::~Test_Stage()
{

}

Заголовок Test_Class:

#ifndef TEST_CLASS_H    
#define TEST_CLASS_H
extern "C"
{
#include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>
}
#include ".\luabind\luabind.hpp"
#include <iostream>
using namespace std;

class Test_Stage;

class Test_Class
{
    public:
        int x;
        Test_Class();
        Test_Class(int num, Test_Stage* stage);
        void shoot_a_bullet(Test_Class* o, int damage);

        Test_Stage *stage;
        ~Test_Class();
    private:

};

#endif TEST_CLASS_H

И, наконец, CPP Test_Class(вызывает у меня много проблем):

#include "test_class.h"
#include"test_stage.h"

void Test_Class::shoot_a_bullet(Test_Class* o, int damage)
{
    cout << "Runned";
    stage->create_bullet(damage, "wowo", x);
}

Test_Class::Test_Class()
{

}

Test_Class::Test_Class(int num, Test_Stage* stg)
{
    stage = stg;
    x = num;
    // Create a new lua state
        lua_State *myLuaState = luaL_newstate();

    // Connect LuaBind to this lua state
    luabind::open(myLuaState);
    luaL_openlibs(myLuaState);


    luabind::module(myLuaState)[
        luabind::class_<Test_Class>("Test_Class")
            .def("shoot_a_bullet", &Test_Class::shoot_a_bullet)
    ];

    /*followed the tutorial codes
    class_<A>("A")
        .def("plus", &plus)*/

    cout << "im here";//just to check how far did the program go
    luaL_dostring(
        myLuaState,
        "shoot_a_bullet(134)\n"
    );
    cout << "I passed it";
    cin.get();
    cin.get();//To pause the program before it closes
    // if you have the time, can you also explain 
    // why do i need two cin.get() to pause the program.
}

Test_Class::~Test_Class()
{

}    

2 ответа

Решение

После многих и многих исследований, я наконец-то нашел решение, хотя я не уверен, насколько оно эффективно, оно работает так, как я хотел.
Таким образом, окончательное решение состоит в том, чтобы зарегистрировать intptr_t преобразован из указателя мне нужно в Луа,(для получения дополнительной информации о intptr_t щелкните здесь(в основном по соображениям безопасности, вы можете увидеть его как некий int дизайн только для указателей)) и передать его статической функции, когда я ее использую

Вот код после модификации:

В Test_Class.cpp, после:

luabind::module(myLuaState)[
    .def("shoot_a_bullet", &shoot_a_bullet)
];// since the functions are static now it will not need the namespace

Я зарегистрировал intptr_t версия указателя:

//first convert pointer to intptr_t
intptr_t stage = (intptr_t)stg;//stg is the pointer

//then register it to lua
//if you try to register a pointer it will give you runtime error
luabind::globals(myLuaState)["stage"] = stage;

Нам также нужно немного изменить функцию:
Во-первых, нам нужно сделать функцию статической, поэтому в заголовочном файле:

//change the line defined the function to
void static shoot_a_bullet(intptr_t stg, int damage);

Теперь мы должны сделать что-то с функцией self:

void Test_Class::shoot_a_bullet(intptr_t stg, int damage)
{
    //we need to convert it back to pointer first, so
    Test_Stage* stage = (Test_Stage*)stg;//this is the part I'm not sure about efficiency 
    stage->create_bullet(damage, "wowo");
}

Так что теперь код с lua будет действительно простым: shoot_a_bullet(stage, 134);

Мы сделали! Жизнь хороша! Этот материал стоил мне 3 недели.

Возможно, вы не поняли, что я сказал, вот полный тестовый код, который я написал:

main.cpp:

#include <iostream>
#include "test_stage.h"

using namespace std;

int x;

int main() {

cin >> x;
cin.get();// clean the \n(when you press enter) after the number
Test_Stage stage = Test_Stage(x);
}

Test_Stage.час:

class Test_Class;
#ifndef TEST_STAGE_H
#define TEST_STAGE_H
extern "C"
{
    #include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>
}
#include ".\luabind\luabind.hpp"
#include <iostream>
#include "test_class.h"
using namespace std;

class Test_Stage
{
    public:
        int x;
        Test_Stage();
        Test_Stage(int num);

        void create_bullet(int damage, string name); /*This is currently useless
        before i have understand how to include each other using foward referance*/
        void create_class(int num);

        Test_Class t_class;

        ~Test_Stage();
    private:

};

#endif

Test_Stageкаст:

#include"test_stage.h"
#include "test_class.h"// and as you see i included both files

Test_Stage::Test_Stage()
{

}

Test_Stage::Test_Stage(int num)
{
    x = num;// a variable specific in this object(to test pointer)
    create_class(num);
}

void Test_Stage::create_bullet(int damage, string name)
{
    cout << "created damage: " << damage << " to " << x << endl;/*using the value
     created in this object to see if pointer is actually working*/
}

void Test_Stage::create_class(int num)
{
    Test_Class t_class = Test_Class(this, num);
}

Test_Stage::~Test_Stage()
{

}

Test_Class.час:

#ifndef TEST_CLASS_H    
#define TEST_CLASS_H
extern "C"
{
#include <lua.h>
    #include <lualib.h>
    #include <lauxlib.h>
}
#include ".\luabind\luabind.hpp"
#include <iostream>
using namespace std;

class Test_Stage;

class Test_Class
{
    public:
        int x;
        Test_Class();
        Test_Class(Test_Stage* stage, int num);
        void static shoot_a_bullet(intptr_t stg, int damage);

        ~Test_Class();
    private:

};

#endif TEST_CLASS_H

И наконец,Test_Class.cpp:

#include "test_class.h"
#include"test_stage.h"

void Test_Class::shoot_a_bullet(intptr_t stg, int damage)
{
    Test_Stage* stage = (Test_Stage*)stg; // intptr_t back to pointer
    stage->create_bullet(damage, "wowo"); // use pointer
}

Test_Class::Test_Class()
{

}

Test_Class::Test_Class(Test_Stage* stg, int num)
{
    intptr_t stage = (intptr_t)stg;
    // Create a new lua state
    lua_State *myLuaState = luaL_newstate();

    // Connect LuaBind to this lua state
    luabind::open(myLuaState);
    luaL_openlibs(myLuaState);


    luabind::module(myLuaState)[
    luabind::def("shoot_a_bullet", &shoot_a_bullet)//again this is static now
    ];

    luabind::globals(myLuaState)["stage"] = stage;

    cout << "I'm here " << endl;//just to check how far did the program go

    luaL_dostring(
        myLuaState,
        "shoot_a_bullet(stage, 134)\n"
    );

    cout << "I passed it"<< endl;
    cin.get();
}

Test_Class::~Test_Class()
{

}    

Повеселись!

Я знаю, что уже поздно, но почему ты просто не сделал

luabind::module(myLuaState)[
    luabind::class_<Test_Class>("Test_Class")
        .def("shoot_a_bullet", &Test_Class::shoot_a_bullet)
];

luabind::globals(myLuaState)["stage"] = stage;

luaL_dostring(
        myLuaState,
        "stage::shoot_a_bullet(134)\n"
    );

Вы все сделали правильно, если вы хотите вызвать функцию-член открытого объекта C++, вам сначала нужно связать его (что вы сделали), затем вы помещаете свой объект в некоторую область действия lua (вы использовали глобальный), а затем просто ссылаетесь на этап объекта и вызов функции с помощью::myfunction

Другие вопросы по тегам