Когдa в моих псевдо-проектах понадобилось использовать скриптовые вставки, по-началу я нашёл пример с биндингом готового MS-JavaScript от IE. Но, примеры были до того скудны, что все эти Dispatch и Variant меня очень быстро доконали и я стал искать нечто удобнее, пусть стороннее и подгружаемое. Первоначально отыскал некий AngelScript и получилось довольно легко (после чудовищных танцев с бубном под дудку MS-IE-JS) всё заставить работать с пол пинка Однако, наткнулся на Белочку и некоторые из её синтаксических особенностей мне приглянулись больше. И я взял её за основу P.S.: Думаю, что на этом форуме есть программисты, для которых "белочка" - не белая горячка Надеюсь, тема будет полезна и остальным. Потому, этот пост не будет содержать никаких вопросов…
Вопрoс первый Спойлер: Имеется некоторый код Код (C++): // Squirrel.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <stdio.h> #include<stdlib.h> #include<string.h> #include<stdarg.h> // TODO: reference additional headers your program requires here #include "../../SQUIRREL3/include/squirrel.h" #include "../../SQUIRREL3/include/sqstdio.h" #include "../../SQUIRREL3/include/sqstdaux.h" #ifdef _MSC_VER #pragma comment (lib ,"../../SQUIRREL3/lib/squirrel.lib") #pragma comment (lib ,"../../SQUIRREL3/lib/sqstdlib.lib") #endif HSQUIRRELVM svm; SQInteger SQF_Test(HSQUIRRELVM v) { SQInteger iArg = sq_gettop(v); //number of arguments SQInteger iValue, jValue, i, j; SQChar const *pszValue; char sz[64] = {0}; wchar_t wsz[64]; SQMemberHandle sqh; union { SQChar const *pszKey; }; while(iArg > 1) { switch(sq_gettype(v, iArg)) { case OT_TABLE: sq_pushnull(v); //null iterator while(SQ_SUCCEEDED(sq_next(v, -2))) { switch(sq_gettype(v, -2)) { case OT_STRING: sq_getstring(v, -2, &pszKey); if(!strcmp(pszKey, "x")) { // Тут начинается довольно проблемный код, // который никак не могу верно сформулировать // Цель: Тупо члену x присвоить числовое значение sq_pushstring(svm, "x", -3); sq_pushinteger(svm, 123); sq_rawset(svm, -5); // Здесь я очень сильно намусорил, перебирая разные варианты, // которые только мог выгуглить и отыскать в официальном мануале... // Не работает НИКАК! Хоть тресни в пятом измерении... // sq_set(v, -1); /* HSQOBJECT hsq_obj; //sq_getstackobj(v, -1, &retObj); //sq_objtointeger(&retObj); // SQ_SUCCEEDED(sq_getmemberhandle(v, -2, &sqh)); //sq_pushstring(v, "x", -1), // sq_pushinteger(v, 123); // sq_setattributes(v, -1); //sq_resetobject(&hsq_obj); //initialize the handle sq_getstackobj(v,-1,&hsq_obj); //retrieve an object handle from the pos –2 hsq_obj._unVal.nInteger ++; sq_pushobject(v, hsq_obj); sq_rawset(v, -1); sq_rawset(v, -2); sq_rawset(v, -3); //sq_addref(v,&hsq_obj); //adds a reference to the object //sq_pushinteger(v, 123); //sq_rawset(v,-1); */ } else break; } sq_pop(v,2); //pops key and val before the nex iteration } sq_pop(v, 2); break; } //sq_pop(v, 1); -- iArg; } return 1; } struct { char *alias; SQInteger (*function)(HSQUIRRELVM); } alf[] = { "Test" ,SQF_Test, NULL, NULL }; SQInteger SQ_register_global_func(HSQUIRRELVM v, SQFUNCTION f, char const *fname) { sq_pushroottable(v); sq_pushstring(v,fname,-1); sq_newclosure(v,f,0); //create a new function sq_newslot(v,-3,SQFalse); sq_pop(v,1); //pops the root table return 0; } void printfunc(HSQUIRRELVM v, const SQChar *s, ...) { char sz[4096]; va_list vl; va_start(vl, s); vprintf(s, vl); // scvprintf(stdout, s, vl); va_end(vl); // Beep(500, 5); } void errorfunc(HSQUIRRELVM v, const SQChar *s, ...) { char sz[4096]; va_list vl; va_start(vl, s); // scvprintf(stderr, s, vl); vprintf(s, vl); va_end(vl); } SQChar szCmd[] = "//\ \r\n function TeSt(_) {\ \r\n _.x = 456;\ \r\n }\ \r\n ::print(\"BEGIN\\r\\n\");\ \r\n local q = {\ \r\n x = null\ \r\n };\ \r\n ::print(\"Initial status: q.x = \" + q.x + \"\\r\\n\");\ \r\n// Выведет на консоль \"q = (null : 0x00000000) ...\" - пока верно\ \r\n Test(q); // Тут в q член x должен стать integer 123\ \r\n ::print(\">After Test(q): q.x = \" + q.x + \"\\r\\n\");\ \r\n// Выведет на консоль то же \"q = (null : 0x00000000)\" - уже не верно (где 123???)\ \r\n TeSt(q); // Тут в q член x должен стать integer 456 и в консоли это выйдет\ \r\n ::print(\">After TeSt(q): q.x = \" + q.x + \"\\r\\n\");\ \r\n ::print(\"FINISH\\r\\n\");\ \r\n"; int main(int argc, char* argv[]) { int i; svm = sq_open(1024); // creates a VM with initial stack size 1024 sq_setforeignptr(svm, 0); sqstd_seterrorhandlers(svm); //registers the default error handlers sq_setprintfunc(svm, printfunc, errorfunc); //sets the print function i = sizeof alf / sizeof *alf; while(i --) SQ_register_global_func(svm, alf[i].function, alf[i].alias); sq_pushroottable(svm); //push the root table(were the globals of the script will be stored)} // SQInteger oldtop = sq_gettop(svm); sq_compilebuffer(svm, szCmd, (int)strlen(szCmd) * sizeof SQChar, "compile", 1); sq_pushroottable(svm); sq_call(svm, 1, SQFalse, SQTrue); sq_settop(svm, oldtop); // printf("Hello World!\n"); return 0; } Выдаёт следующее: Код (DOS): BEGIN Initial status: q.x = (null : 0x00000000) >After Test(q): q.x = (null : 0x00000000) >After TeSt(q): q.x = 456 FINISH Hello World! Press any key to continue P.S.: Кто-нибудь может мне помочь? Что-то в сети не могу выгуглить ни примера, ни намёка, каким образом в готовой данной скриптом таблице изменять отдельные её члены… (В своей утилите я перед вызовом callback-функции пользователя сейчас тупо заполняю таблицу из нескольких сотен членов данными из файла (FileMapping), а после возврата - обратно её сканирую и все значения скидываю обратно в файл. А это, сами понимаете, слишком много лишнего труда и нагрузки. Суть функции, которую пытаюсь расписать, в том, чтобы сканировать всю таблицу и числовые значения встречаемых членов скидывать в соответствующее место файла. Что достаточно легко. А вот члены, значения которых - null, функция должна, наоборот, прочитать из файла и вернуть им значение в таблицу. С чем я не могу справиться никак с сентября прошлого года , когда решил таки оптимизировать это дело… А официальный форум даже не принимает моей темы ) Спасибо!
попробуй редактировать бд чрез консольную утилиту ==>> если пашет, то в своей проге пиши/читай бд чрез сию тулзу.
Вчерa таки добился своего (кошмар, пол года топтаться из-за пустячка): Спойлер: Имеется некоторый исправленный код Код (C++): #include <stdio.h> #include<stdlib.h> #include<string.h> #include<stdarg.h> #include "../../SQUIRREL3/include/squirrel.h" #include "../../SQUIRREL3/include/sqstdio.h" #include "../../SQUIRREL3/include/sqstdaux.h" #ifdef _MSC_VER #pragma comment (lib ,"../../SQUIRREL3/lib/squirrel.lib") #pragma comment (lib ,"../../SQUIRREL3/lib/sqstdlib.lib") #endif HSQUIRRELVM svm; SQInteger SQF_Test(HSQUIRRELVM v) { SQInteger iArg = sq_gettop(v); //number of arguments SQInteger iValue, jValue, i, j; SQChar const *pszValue; char sz[64] = {0}; wchar_t wsz[64]; SQMemberHandle sqh; union { SQChar const *pszKey; }; while(iArg > 1) { switch(sq_gettype(v, iArg)) { case OT_TABLE: sq_pushnull(v); //null iterator while(SQ_SUCCEEDED(sq_next(v, -2))) { switch(sq_gettype(v, -2)) { case OT_STRING: sq_getstring(v, -2, &pszKey); if(!strcmp(pszKey, "x")) { sq_pushstring(v, "x", -1); sq_pushinteger(v, 123); sq_set(v, -9); } break; } sq_pop(v,2); //pops key and val before the nex iteration } sq_pop(v, 2); break; } //sq_pop(v, 1); -- iArg; } return 1; } struct { char *alias; SQInteger (*function)(HSQUIRRELVM); } alf[] = { "Test" ,SQF_Test, NULL, NULL }; SQInteger SQ_register_global_func(HSQUIRRELVM v, SQFUNCTION f, char const *fname) { sq_pushroottable(v); sq_pushstring(v,fname,-1); sq_newclosure(v,f,0); //create a new function sq_newslot(v,-3,SQFalse); sq_pop(v,1); //pops the root table return 0; } void printfunc(HSQUIRRELVM v, const SQChar *s, ...) { char sz[4096]; va_list vl; va_start(vl, s); vprintf(s, vl); va_end(vl); } void errorfunc(HSQUIRRELVM v, const SQChar *s, ...) { char sz[4096]; va_list vl; va_start(vl, s); vprintf(s, vl); va_end(vl); } SQChar szCmd[] = "//\ \r\n function TeSt(_) {\ \r\n _.x = 456;\ \r\n }\ \r\n ::print(\"BEGIN\\r\\n\");\ \r\n local q = {\ \r\n x = null\ \r\n };\ \r\n ::print(\"Initial status: q.x = \" + q.x + \"\\r\\n\");\ \r\n// Write to console \"q = (null : 0x00000000) ...\" - right!\ \r\n Test(q); // Here are q.x is setted to a integer 123\ \r\n ::print(\">After Test(q): q.x = \" + q.x + \"\\r\\n\");\ \r\n// Write to console now \"q = 123\" - very nice)\ \r\n TeSt(q); // Here are q.x is setted to a integer 456 - right, but through TeSt...\ \r\n ::print(\">After TeSt(q): q.x = \" + q.x + \"\\r\\n\");\ \r\n ::print(\"FINISH\\r\\n\");\ \r\n"; int main(int argc, char* argv[]) { int i; svm = sq_open(1024); // creates a VM with initial stack size 1024 sq_setforeignptr(svm, 0); sqstd_seterrorhandlers(svm); //registers the default error handlers sq_setprintfunc(svm, printfunc, errorfunc); //sets the print function i = sizeof alf / sizeof *alf; while(i --) SQ_register_global_func(svm, alf[i].function, alf[i].alias); sq_pushroottable(svm); //push the root table(were the globals of the script will be stored)} // SQInteger oldtop = sq_gettop(svm); sq_compilebuffer(svm, szCmd, (int)strlen(szCmd) * sizeof SQChar, "compile", 1); sq_pushroottable(svm); sq_call(svm, 1, SQFalse, SQTrue); sq_settop(svm, oldtop); // return 0; } Выдаёт следующее: Код (DOS): BEGIN Initial status: q.x = (null : 0x00000000) >After Test(q): q.x = 123 >After TeSt(q): q.x = 456 FINISH Press any key to continue P.S.: Банальная невнимательность и довольно плохое понимание работы Lua-стека…