r2500 Posted February 15, 2011 Report Posted February 15, 2011 I would like to be able to call event.offset(offset, type, "fn") where fn is a function in a Lua module included in the main program with a "require" statement. It is possible to do this by making "fn" the name of a function in the main program that in turn calls the function in the module, but that means that the main program has to know about details of the "required" module, and that's undesirable. That I can't make it work can be seen in the code that follows ... "Event proc not found". Is what I want possible using WideClient? Richard What follows are two very short Lua programs, one that resides in the modules subdirectory, and a "main" program to be run by WideClient. --==========Start of file "modules\M.lua"============== module(..., package.seeall) function f(offset, value) print(string.format("heading %d", value)) -- ignoring scaling needed in the real code end -- this doesn't work --event.offset(0x7CC, "UW", "f") --==============end of file=============== -- Start of Initial.lua require "M" function doit(offset, value) M.f(offset, value) end -- these both print "type function" print(string.format("Trying M.f, type %s", type(M.f))) print(string.format('Trying _G["M"]["f"] , type %s', type(_G["M"]["f"]))) -- this works event.offset(0x7CC, "UW", "doit") -- these don't. They both generate a compile time error --[[ ********* LUA: "Initial" Log [from WideClient] ********* Date (dmy): 07/02/11, Time 16:46:36.415: Client name is FRANZ 546 LUA: beginning "C:\Do Flight\Initial.LUA" 561 LUA: Trying M.f, type function -- from the print statement above 561 LUA: Trying _G["M"]["f"] , type function -- ditto 561 *** LUA Error: C:\Do Flight\Initial.LUA:27: Event proc not found 561 LUA: ended "C:\Do Flight\Initial.LUA" ********* LUA execution terminated: Log Closed ********* --]] --[[ -- remove the comment delineators to see the error event.offset(0x07CC, "UW", '_G["M"]["f"]') -- heading bug event.offset(0x07CC, "UW", "M.f") -- heading bug --]] --===============end of file====================
Pete Dowson Posted February 16, 2011 Report Posted February 16, 2011 I would like to be able to call event.offset(offset, type, "fn") where fn is a function in a Lua module included in the main program with a "require" statement. Hmm. I don't (yet) know how to do that. At present the procedure is obtained by using the C function "lua_getglobal". This references the globals index by LUA_GLOBALSINDEX. Evidently that doesn't contain all the names in modules even as a list named for the module, or if it does just using "getglobal" with the string name "m.fn" doesn't cut it. I've had another read through the relevant sections of the Lua books I have and I don't think I understand the internal data structures well enough to know how to implement it. Obviously the interpreter must know where "m.f" is but how do I call it from C code? The lua_pcall function needs the function pushed onto the stack. I get that using lua_getglobal. Do you know how to make that work with functions in a module? What happens if you define local names for the functions in the module, like myf = m.fn and then use "myf" as the function. Does that work? Maybe I have to parse the string to separate "m" from "fn". Then get "m" as a global, check that it's a table (lua_istable) and then, if it is, see if I can access the field in it named "fn" and check that's a function. I might experiment on those lines. Of course it could go further. "m.t.fn" there t is a table of functions in module m. Et cetera. I'd have to keep going whilst I found tables till i found a function. Hmmm. It is possible to do this by making "fn" the name of a function in the main program that in turn calls the function in the module, but that means that the main program has to know about details of the "required" module, and that's undesirable. But that makes no sense. If you know "f" is a function in "M" then you can call it from a local function in the main program. What's the difference between doing that and making it a literal string in the event library call? Either way the main program has to know that function f is in module M. What follows are two very short Lua programs, one that resides in the modules subdirectory, and a "main" program to be run by WideClient. I assume you don't mean the FS modules folder? ;-) Regards Pete
r2500 Posted February 16, 2011 Author Report Posted February 16, 2011 Hmm. I don't (yet) know how to do that. At present the procedure is obtained by using the C function "lua_getglobal". This references the globals index by LUA_GLOBALSINDEX. Evidently that doesn't contain all the names in modules even as a list named for the module, or if it does just using "getglobal" with the string name "m.fn" doesn't cut it. I've had another read through the relevant sections of the Lua books I have and I don't think I understand the internal data structures well enough to know how to implement it. Obviously the interpreter must know where "m.f" is but how do I call it from C code? The lua_pcall function needs the function pushed onto the stack. I get that using lua_getglobal. Do you know how to make that work with functions in a module? What happens if you define local names for the functions in the module, like myf = m.fn and then use "myf" as the function. Does that work? Maybe I have to parse the string to separate "m" from "fn". Then get "m" as a global, check that it's a table (lua_istable) and then, if it is, see if I can access the field in it named "fn" and check that's a function. I might experiment on those lines. Of course it could go further. "m.t.fn" there t is a table of functions in module m. Et cetera. I'd have to keep going whilst I found tables till i found a function. Hmmm. But that makes no sense. If you know "f" is a function in "M" then you can call it from a local function in the main program. What's the difference between doing that and making it a literal string in the event library call? Either way the main program has to know that function f is in module M. I assume you don't mean the FS modules folder? ;-) Regards Pete Last things first, correct, I don't mean the FS modules folder, but one I created as a sub directory of the folder in which WideClient is located. Then "require" knows where to look without my doing anything with the package loaded/loadlib/etc code. I'm very new to Lua and there are vast areas in which mis-understanding could get me lost for a long time<g>. Which means I know nothing about the C code underlying Lua. A quick test says that "myf = M.f" does work. But I don't want the top level code to know what's in M, so to speak. I'll have to experiment more with name passing though my data structures, though I may not have time to do so for a day. Since myf = M.f worked (at least once<g>), I'm wondering if the code in the event library (or the C code it calls) does some massaging of the string function, like removing brackets, dots, and the like, to make it a simple name.I have experimented a bit with printing out environments and it looks as if everything is where one expects it (and event.offset should be able to see the modular structure). Too bad the error message doesn't say which proc not found. Richard
r2500 Posted February 16, 2011 Author Report Posted February 16, 2011 Last things first, correct, I don't mean the FS modules folder, but one I created as a sub directory of the folder in which WideClient is located. Then "require" knows where to look without my doing anything with the package loaded/loadlib/etc code. I'm very new to Lua and there are vast areas in which mis-understanding could get me lost for a long time<g>. Which means I know nothing about the C code underlying Lua. A quick test says that "myf = M.f" does work. But I don't want the top level code to know what's in M, so to speak. I'll have to experiment more with name passing though my data structures, though I may not have time to do so for a day. Since myf = M.f worked (at least once<g>), I'm wondering if the code in the event library (or the C code it calls) does some massaging of the string function, like removing brackets, dots, and the like, to make it a simple name.I have experimented a bit with printing out environments and it looks as if everything is where one expects it (and event.offset should be able to see the modular structure). Too bad the error message doesn't say which proc not found. Richard Found a comment that says that Lua_getglobal does not handle "." Maybe it doesn't handle "[]" notation either.
Pete Dowson Posted February 16, 2011 Report Posted February 16, 2011 A quick test says that "myf = M.f" does work. Okay. That helps. Probabably if I parse the string "M.f" and step down through tables it will work. I'll try it and let you know. But I don't want the top level code to know what's in M, so to speak. So if it doesn't know that "f" is in "M" how does it know to use the string "M.f" in the event function? Since myf = M.f worked (at least once<g>), I'm wondering if the code in the event library (or the C code it calls) does some massaging of the string function, like removing brackets, dots, and the like, to make it a simple name. No, it's my code. I'm calling a function called "getglobal" which takes the name and returns the function pointer for me to call. "M.f" is not a function name but a table name (M) and a function name "f". I think it's just that the getglobal call doesn't parse the name to separate table pointer and content. I'll need to do that in my code I think. Too bad the error message doesn't say which proc not found. Unless you put everything on one line, surely the line number is a BIG clue? I use "ultraedit32" as my editor and that provides line numbers. Regards Pete
Pete Dowson Posted February 16, 2011 Report Posted February 16, 2011 Okay. That helps. Probably if I parse the string "M.f" and step down through tables it will work. I'll try it and let you know. Yes, it works. I've allowed functions in tables ("M.fn") and functions in tables in tables, etc ( "M.t.fn" etc), up to a limit of 63 characters between the "". Facility added in FSUIPC 3.989x, 4.662 and WideClient 6.843 now available from the Download Links subforum. Regards Pete
r2500 Posted February 17, 2011 Author Report Posted February 17, 2011 Yes, it works. I've allowed functions in tables ("M.fn") and functions in tables in tables, etc ( "M.t.fn" etc), up to a limit of 63 characters between the "". Facility added in FSUIPC 3.989x, 4.662 and WideClient 6.843 now available from the Download Links subforum. Regards Pete Ah, how pleasant. That works very nicely. Code is much cleaner now. I just ran across this note on stack overflow. I imagine this is what you're doing. This function is really useful at runtime to construct function "pointers" when you have the name (string) and the name of the module (string) in which the function resides. Of course, often, the module name is the file name, but probably it's better if that doesn't appear in the code explicitly. Something like module(..., package.seeall) modname = ... .. "." --best use of 5 periods in a Lua statement!? fn = findfunction(modname .. "some function name as string") --pass this fn in data structures and it can be used without needing to resolve the "." structure On an irrelevant matter, yes I do use an editor with line numbers. After over three decades of Unix, I'm a vi addict and so use gvim. Newer editors handle class structure and the like better, but ... Richard
Pete Dowson Posted February 17, 2011 Report Posted February 17, 2011 I just ran across this note on stack overflow. I imagine this is what you're doing. No. My code is in C and calls the exported C routines in the Lua interpreter -- I just split off the names using the '.' delimiter and use "lua_getfield", iteratively whilst they refer to tables (checked using "lua_istable") till I reach a function (checked by using "lua_isfunction"). Previously I was just using "lua_getglobal" (which is a special case of "lua_getfield") and "lua_isfunction". It's very similar still except for burrowing through tables. Regards Pete
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now