Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Builder
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.69/13: Рейтинг темы: голосов - 13, средняя оценка - 4.69
MqKnJt
1 / 1 / 0
Регистрация: 24.12.2009
Сообщений: 4
#1

Остановка скриптов, luabind и потоки

23.02.2010, 14:25. Просмотров 2267. Ответов 22
Метки нет (Все метки)

Интересно, как вы реализуете пользовательскую остановку скрипта? Я пока что знаю только один способ корректно прервать скрипт:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
extern "C" {
 
void lua_hook(lua_State *L, lua_Debug *ar) {
 
    Application->ProcessMessages();
    if (Form1->Aborted)
        luaL_error(L, "Aborted by user");
}
 
}
 
// ...
 
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    L = lua_open();
 
    lua_sethook (L, lua_hook, LUA_MASKCOUNT, 1);
 
    // ...
}
 
// ...
 
void __fastcall TForm1::AbortButtonClick(TObject *Sender)
{
    AbortButton->Enabled = false;
    Aborted = true;
}

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
23.02.2010, 14:25
Ответы с готовыми решениями:

Выход (остановка) функции
Где в этой функции нужно поставить break или goto что бы после нахождения...

Остановка USB устройств
Здраствуйте. Стоит задача: необходимо написать программу на С++, которая...

Не работает остановка потоков
Ребята помогите пожалуйста, не могу разобраться с остановкой потоков. Вроде при...

Остановка выполнения программы....
Есть прога на Builder'е 6.0, можно ли по нажатии кнопки прекращать выполнение...

Правильная остановка потока
Есть поток, в которым выполняется запрос. При закрытии формы, нужно...

22
black-eye
18 / 18 / 1
Регистрация: 24.09.2009
Сообщений: 98
24.02.2010, 14:12 #2
Ну я не знаю... Моя задача была объяснить ,KTYJIX, скрипт. А за остановку, спасибо

Добавлено через 23 часа 43 минуты
Помогите правильно построить код

main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class TFunctionsLua : public TLua
{
public:
//---------------------------------------------------------------------------
int Lua_ShowMessage(lua_State*st)
{
TLua lua(st);
int top=lua.GetTop();
if(top==1) ShowMessage(lua.ToString(top));
return 0;
}
void RegFunctions()
{
RegFunction("ShowMessage",Lua_ShowMessage);
}
//---------------------------------------------------------------------------
};
Кидаю класс TLua, составленный Otaka

class TLua
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
class TLua
{
lua_State*lua;
bool isowner;
public:
TLua()
     {
     lua=luaL_newstate();
     isowner=true;
     if(lua==NULL)
          {
          lua=NULL;
          throw Exception("Lua was not initialized");
          }
     LoadAllStdLibs();
     }
TLua(lua_State*lua_state)
     {
     lua=lua_state;
     isowner=false;
     }
 
~TLua()
     {
     if(isowner==true)
          {
          if(lua!=NULL)
               {
               lua_close(lua);
               }
          }
     }
__inline void LoadAllStdLibs()
     {
     luaL_openlibs(lua);
     }
__inline void DoStr(char*str)
     {
     int res=luaL_dostring(lua, str);
     if(res!=0)throw Exception(lua_tostring(lua,-1));
     }
 
__inline void DoFile(char*str)
     {
     int res=luaL_dofile(lua, str);
     if(res!=0)throw Exception(lua_tostring(lua,-1));
     }
__inline int RegFunction(char*name,int(*poin)(lua_State*st))
     {
     lua_register(lua,name,poin);
     return 0;
     }
__inline void GlobalField(char*field)
     {
     lua_getfield(lua,LUA_GLOBALSINDEX,field);
     }
__inline int ToInteger(int index)
     {
     return lua_tointeger(lua,index);
     }
__inline double ToNumber(int index)
     {
     return lua_tonumber(lua,index);
     }
__inline const char*ToString(int index)
     {
     return lua_tostring(lua,index);
     }
__inline void Push(int i)
     {
     lua_pushinteger(lua,i);
     }
__inline void Push(char*str)
     {
     lua_pushstring(lua,str);
     }
__inline void PushNil()
     {
     lua_pushnil(lua);
     }
__inline void PushNumber(double d)
     {
     lua_pushnumber(lua,d);
     }
__inline void  Pop(int count)
     {
     lua_pop(lua,count);
     }
__inline int GetTop()
     {
     return lua_gettop(lua);
     }
__inline void SetTop(int top)
     {
     lua_settop(lua,top);
     }
__inline int GetType(int index)
     {
     return lua_type(lua,index);
     }
__inline const char*GetTypeName(int TypeCode)
     {
     return lua_typename(lua,TypeCode);
     }
void Error()
     {
     lua_error(lua);
     }
};
0
black-eye
18 / 18 / 1
Регистрация: 24.09.2009
Сообщений: 98
25.02.2010, 22:20 #3
ну хоть кто нибудь, хоть что-то знает))
0
Otaka
1827 / 685 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
25.02.2010, 22:26 #4
Делать функцию hook это плохо, так как она будет вызываться практически после каждого твоего Луа оператора, с заполнением отладочных полей(хотя тут как настроить). Наверное, лучше бы запускать в отдельном потоке, а потом его убивать. Но тут нужно проверить, будут ли у нас утечки памяти(я боюсь что будут). Нужно тысячу или больше раз сделать запустить/убить, и посмотреть, изменился ли размер занимаемой памяти.
0
black-eye
18 / 18 / 1
Регистрация: 24.09.2009
Сообщений: 98
25.02.2010, 22:29 #5
Т.е. мне лучше не делать hook, я правильно понял? Вообще-то я уже реализовал код через поток, но хотелось бы выслушать твоё мнение, может что-нить получше будет Хотя этот код очень сырой, нужна проверка и помощь

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
//---------------------------------------------------------------------------
#include <vcl.h>
#include "ttlist.h" //Твой класс
#include "lua.h"
 
TLua Lua;
 
//---------------------------------------------------------------------------
class TMTH : public TThread
{
private:
protected:
//TFunctionsLua fl;
void __fastcall Execute()
{
FreeOnTerminate = true;
try{Lua.DoStr(str.c_str());}
catch(...){Suspend(); ShowMessage("Thread terminated!!!");}
ShowMessage(""); //Это для отладки
}
public:
AnsiString str;
//---------------------------------------------------------------------------
__fastcall TMTH(bool CreateSuspended)
        : TThread(CreateSuspended)
{
}
};
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
TTList<TMTH*>*mths=new TTList<TMTH*>();
//---------------------------------------------------------------------------
int Lua_ShowMessage(lua_State*st)
{
TLua lua(st);
int top=lua.GetTop();
if(top==1) ShowMessage(lua.ToString(top));
return 0;
}
//---------------------------------------------------------------------------
int Lua_CreateThread(lua_State*st)
{
TLua lua(st);
TMTH *m=new TMTH(true);
m->Priority=tpNormal;
int c=mths->Count;
mths->Add(m);
mths->Get(c)->Resume();
lua.Push(c);
return 1;
}
//---------------------------------------------------------------------------
int Lua_ThreadScript(lua_State*st)
{
TLua lua(st);
int top=lua.GetTop();
if(top==2) mths->Get(lua.ToInteger(top-1))->str=lua.ToString(top);
return 0;
}
//---------------------------------------------------------------------------
int Lua_StartThread(lua_State*st)
{
TLua lua(st);
int top=lua.GetTop();
if(top==1) mths->Get(lua.ToInteger(top))->Resume();
return 0;
}
//---------------------------------------------------------------------------
int Lua_StopThread(lua_State*st)
{
TLua lua(st);
int top=lua.GetTop();
if(top==1)
{
try{mths->Get(lua.ToInteger(top))->Suspend();}
__finally {}
}
return 0;
}
//---------------------------------------------------------------------------
int Lua_DelThread(lua_State*st)
{
TLua lua(st);
int top=lua.GetTop();
if(top==1)
{
try
{
mths->Get(lua.ToInteger(top))->Suspend();
delete mths->Get(lua.ToInteger(top));
mths->Delete(lua.ToInteger(top));
}__finally {}
}
return 0;
}
//---------------------------------------------------------------------------
void RegFunctions()
{
Lua.RegFunction("ShowMessage",Lua_ShowMessage);
Lua.RegFunction("CreateThread",Lua_CreateThread);
Lua.RegFunction("DelThread",Lua_DelThread);
Lua.RegFunction("StartThread",Lua_StartThread);
Lua.RegFunction("StopThread",Lua_StopThread);
Lua.RegFunction("ThreadScript",Lua_ThreadScript);
}
//---------------------------------------------------------------------------
0
Otaka
1827 / 685 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
25.02.2010, 23:08 #6
Ну, как бы оно так, но меня очень(ООЧЕНЬ), смущает то, что ты очищаешь свой "менеджер потоков", из вызова скриптовой функции DelThread, а если поток просто закончится и выйдет, то у нас в списке будет висящий указатель на непонятно что. Поэтому тебе бы сделать еще обработчик TThread::OnTerminate. и прописать корректное удаление указателя потока из списка.
И еще проверь, можно ли вот так вот прерывать выполнение луа программы. Сделай в цикле на 1000 раз создание и убивание потока, и смотри на память.
0
KTYJIX
Задающий вопросы (%
16 / 15 / 0
Регистрация: 09.05.2009
Сообщений: 168
25.02.2010, 23:51 #7
Отака, я тут на статейку наткнулся - http://younggamedeveloper.blogspot.com/2008/04/c-lua.html
Тут при помощи библиотеки luabind, парень привязывает С++ классы к луа.

А в нашем случае как быть?
1
black-eye
18 / 18 / 1
Регистрация: 24.09.2009
Сообщений: 98
26.02.2010, 14:46 #8
Otaka, хорошо, проверю... А как сделать примерно такой код выполнимым
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
//LUA_SCRIPT//
start_thread("MAIN")
wait 0
player=Actor.Create(0)//где 0 тип персонажа, т.е. 0 - игрок
 
script_thread("MAIN")
{
wait 0
if ActorDead(player) then
бла бла бла
end_thread("MAIN")
else //Здесь я хочу, чтоб этот скрипт выполнялся ещё раз
}
Вопрос, как сделать так?

PS Я раньше занимался скриптописанием для GTA: San Andreas и там примерно такая структура, как я написал выше, хотя если поточнее:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
thread 'MAIN'
wait 0
Model.Load(#PLAYER)
 
:MAIN_1
wait 0
if
Model.Loaded(#PLAYER)
jump_false @MAIN_1
 
:MAIN_2
wait 0
$PLAYER=Actor.Create(type_of_actor,model,pos_x,pos_y,pos_z)
 
:MAIN_3
wait 0
Model.Destroy(#PLAYER)
end_thread
Примерно такой код
0
Otaka
1827 / 685 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
26.02.2010, 20:46 #9
KTYJIX, luabind это очень хорошо, но как и большинство С++шных библиотек с полпинка на билдере оно не запустилось, а делать ООП на lua мне никогда не было нужно, поэтому я и не заморачивал себе голову.

black-eye, я, честно говоря,так и не понял, в чем вопрос. Как сделать потоки на Луа? почитай про coroutines(это некоторое подобие потоков встроенными луа средствами)
0
black-eye
18 / 18 / 1
Регистрация: 24.09.2009
Сообщений: 98
26.02.2010, 20:54 #10
я хочу чтоб в луа создался поток на проверку чего-либо и пока не вернётся значение с потока, то скрипт дальше не выполняется, а зацикливается на этой проверке

Добавлено через 50 секунд
Честно говоря я уже сам запутался
0
Otaka
1827 / 685 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
26.02.2010, 21:05 #11
так я и говорю же, создаёшь луапоток thread=coroutine.create(f), где f - это функция Lua, потом его запускаешь, coroutine.resume(t). Вот только подпрограммы не будут сами отдавать процессор, поэтому это нужно делать принудительно, ставя в циклах coroutine.yield().
Вот и все, в скрипте у тебя главный поток скриптовой программы, и пара потоков которые проверяю что либо(например ту же смерть персонажа). Но ту же смерть персонажа, мне кажется, лучше не ждать в скрипте, а сделать так, чтобы программа посылала сообщения луа скрипту о каком-либо событии(таймер, смерть объекта, вход одного объекта в другой итд... типа как триггеры в скриптах Warcraft)
1
black-eye
18 / 18 / 1
Регистрация: 24.09.2009
Сообщений: 98
26.02.2010, 21:08 #12
Otaka, помоги мне написать банальный пример, если не трудно.
0
Otaka
1827 / 685 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
26.02.2010, 21:41 #13
Ммда, вот так вот сболтнул про луапотоки, помнил, что где-то читал, но ни разу не пробовал, а вот обратившись к официальной документации(http://www.lua.ru/doc/2.11.html) мы видим, что эти потоки есть чем-то очень странным. Их нужно активировать вручную, и вручную переключать. Как это прикрутить к твоей задачке я даже и не знаю.
Сделай, наверное, несколько функций в С++(PersKilled, Timer и другие), зарегистрируй их для скрипта, и при убитии какого-нибудь персонажа вызывай эту функцию, и передавай ей ID того объекта который умер(или что там с ним случилось), и скрипт будет это обрабатывать.
1
black-eye
18 / 18 / 1
Регистрация: 24.09.2009
Сообщений: 98
26.02.2010, 21:45 #14
жёстко... мдэ... тогда лучше попробовать использовать luabind
0
Otaka
1827 / 685 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
26.02.2010, 21:47 #15
Попробуй, потом расскажешь, как там все делается.
1
black-eye
18 / 18 / 1
Регистрация: 24.09.2009
Сообщений: 98
26.02.2010, 21:53 #16
Otaka, помоги перевести луабинд в билдер
0
Otaka
1827 / 685 / 55
Регистрация: 11.12.2008
Сообщений: 1,019
26.02.2010, 22:12 #17
Ну я ведь говорил, что у меня оно так и не заработало(но наверное я не очень-то и старался).
Качаешь с сайта http://sourceforge.net/projects/luabind/ исходники этого луабинда, потом качаешь отсюда вот http://www.boost.org/ библиотеку буст, если у тебя её еще нет, потом в свой проект подключаешь
#include<luabind.hpp>, попутно прописав пути в настройках проекта к этой самой luabind и boost. Нажимаешь F9, получаешь кучу ошибок, исправляешь их, снова F9 итд.
К сожалению, у Билдера проблемы с поддержкой всех стандартов С++, вот оно часто и артачится.
1
KTYJIX
Задающий вопросы (%
16 / 15 / 0
Регистрация: 09.05.2009
Сообщений: 168
27.02.2010, 00:38 #18
Эх...
Отака, ситуация такая - опыта в таких делах, а именно отладка кода под билдер, у меня мало.
И такие ошибки, как там, мне трудно решить.
Я понимаю что это муторное и трудное занятие, но прошу тебя, как человека, имеющего за плечами громадный опыт работы с билдером, помочь мне и всему русскому народу.
Надеюсь, ты найдёшь свободное время в этом поколупаться (%

Спасибо за всё.
1
black-eye
18 / 18 / 1
Регистрация: 24.09.2009
Сообщений: 98
27.02.2010, 14:48 #19
Присоединяюсь

Добавлено через 1 минуту
Я тоже буду пробовать запустить на билдере... Ведь у меня получилось перевести DirectX 9 в билдер () А он немного труднее, я прав?

Добавлено через 17 минут
У меня есть идея как реализовать такой луа скрипт:

C++
1
2
3
4
5
6
7
8
thread 'MAIN'
....бла....бла....бла....
create_thread TEST
end_thread
 
thread 'TEST'
....бла....бла....бла....
end_thread
Ведь можно сначала просто прочесть файл, только каждую строчку заносить в TList, а потом с помощью поиска находить "thread", и "end_thread". Потом то, что между этими двумя функциями(так назовём) заносим в ещё один TList, а потом уже этот, перенесённый скрипт выполняем, обрабатываем в другом потоке и сразу как поток завершиться, он сразу же удаляется.
0
KTYJIX
Задающий вопросы (%
16 / 15 / 0
Регистрация: 09.05.2009
Сообщений: 168
01.03.2010, 23:18 #20
После продолжительных анальных мучений, Я нашел невозможным заставить работать С++ Builder вместе с luabind. И решил идти обходным путем. Из luabind'a мне нужно было привязка классов С++ к Lua, после недолгих поисков, Я нашел прекрасный враппер классов, написанный nornagon'ом, код которого занимает всего 70 строчек. Очень удобный и понятный + 100% совместимость с C++ Builder.

В самом коде вы найдете понятный пример его использования.

Так что, предоставляю вашему вниманию: Luna

В связи с этим назрел вопрос к Отаке:
У нас же враппер свой, правильно?(TLua)
Все его функции работают в потоке, который указан в самом TLua.
Но для регистрации классов через luna мне нужна ссылка на этот поток(поток TLua), как мне её достать?
0
Вложения
Тип файла: rar luna.rar (1.6 Кб, 74 просмотров)
01.03.2010, 23:18
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
01.03.2010, 23:18

Остановка обработки OnClose
Можно ли как то остановить обработку события OnClose ? Например при нажатии на...

Остановка рисования в Image
Добрый день! Не могу придумать как останавливать рисование: При движении мыши...

Остановка по нажатию кнопки
Подскажите пожалуста. Необходимо чтобы программа выполняла некий код по...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Закрытая тема Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru