163 posts
Location
Pennsylvania
Posted 16 March 2014 - 05:21 AM
So I have a API that needs to know which directory it's in. To find this, I run a command on the first line:
local dirName = shell.dir()
For some reason, when I run this program, I get:
apiName.lua:1: attempt to index ? (a nil value)
When I try shell.dir() in the lua program, it works fine. What am I doing wrong?
EDIT: I think I figured it out. Correct me if I'm wrong, but it looks like when you use os.loadAPI(), it's not being loaded in a particular folder, so shell.dir() doesn't work right. (And/or doesn't exist?)
Edited on 16 March 2014 - 04:24 AM
7508 posts
Location
Australia
Posted 16 March 2014 - 05:29 AM
not quite. basically what it is is that whenever you load an api with
os.loadAPI it does not get a reference to the shell API, only your main program gets that, you can however supply the API to your own so that you can use it.
Example main program (startup)
os.loadAPI("api")
api.setShell(shell)
api.doSomething()
Example API (api)
local shell
function setShell( t )
shell = t
end
function doSomething()
print("The current shell directory is: ", shell.dir())
end
163 posts
Location
Pennsylvania
Posted 16 March 2014 - 05:46 AM
not quite. basically what it is is that whenever you load an api with
os.loadAPI it does not get a reference to the shell API, only your main program gets that, you can however supply the API to your own so that you can use it.
Example main program (startup)
os.loadAPI("api")
api.setShell(shell)
api.doSomething()
Example API (api)
local shell
function setShell( t )
shell = t
end
function doSomething()
print("The current shell directory is: ", shell.dir())
end
Thanks. It's a shame that there's no easier way to do that.
7508 posts
Location
Australia
Posted 16 March 2014 - 06:04 AM
Thanks. It's a shame that there's no easier way to do that.
well you could also do your own custom implementation of
os.loadAPI to actually add in a reference to shell.
8543 posts
Posted 16 March 2014 - 07:32 AM
Could always try getfenv(2).shell.dir(), if you can guarantee that your API will only be called by programs with the shell "API" in their environment. If it starts getting called by other API functions or something, all bets are off.
The advantage to this method is that if multiple shells are instantiated, this will always get the "correct" one.
163 posts
Location
Pennsylvania
Posted 16 March 2014 - 10:24 PM
Well, I implemented that first method, but now when I call load it, it doesn't seem to be loaded properly:
os.loadAPI(shell.dir()..'test.sys/api/apiName.lua')
print(apiName or 'nil')
prints 'nil' instead of 'tablexxxxxx'
Any idea as to what's wrong?
1281 posts
Posted 16 March 2014 - 10:59 PM
I've never tried loading an api with a dot in it's name, but i suspect that might cause problems. Try removing it.
7508 posts
Location
Australia
Posted 17 March 2014 - 02:24 AM
yeah it causes problems. I've made a
os.loadAPI function which fixes the problem with extensions
function loadAPI(path)
local name = string.match(fs.getName(path), "(%a+)%.?.-")
local env = setmetatable({}, { __index = _G })
local func, err = loadfile(path)
if not func then
return false, printError(err)
end
setfenv(func, env)
func()
local api = {}
for k,v in pairs(env) do
api[k] = v
end
_G[name] = api
return true
end
and if you want to add the reference to the
shell for it change the line
local env = setmetatable({}, { __index = _G })
to
local env = setmetatable({shell = shell}, { __index = _G })
Edited on 17 March 2014 - 01:24 AM
163 posts
Location
Pennsylvania
Posted 17 March 2014 - 07:20 AM
yeah it causes problems. I've made a
os.loadAPI function which fixes the problem with extensions
function loadAPI(path)
local name = string.match(fs.getName(path), "(%a+)%.?.-")
local env = setmetatable({}, { __index = _G })
local func, err = loadfile(path)
if not func then
return false, printError(err)
end
setfenv(func, env)
func()
local api = {}
for k,v in pairs(env) do
api[k] = v
end
_G[name] = api
return true
end
and if you want to add the reference to the
shell for it change the line
local env = setmetatable({}, { __index = _G })
to
local env = setmetatable({shell = shell}, { __index = _G })
Thanks so much for all the help!