Jump to content




Not entirely sure what's wrong here...


  • You cannot reply to this topic
8 replies to this topic

#1 skwerlman

  • Members
  • 163 posts
  • LocationPennsylvania

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 by skwerlman, 16 March 2014 - 05:24 AM.


#2 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

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


#3 skwerlman

  • Members
  • 163 posts
  • LocationPennsylvania

Posted 16 March 2014 - 05:46 AM

View Posttheoriginalbit, on 16 March 2014 - 05:29 AM, said:

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.

#4 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

Posted 16 March 2014 - 06:04 AM

View Postskwerlman, on 16 March 2014 - 05:46 AM, said:

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.

#5 Lyqyd

    Lua Liquidator

  • Moderators
  • 8,465 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.

#6 skwerlman

  • Members
  • 163 posts
  • LocationPennsylvania

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?

#7 CometWolf

  • Members
  • 1,283 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.

#8 theoriginalbit

    Semi-Professional ComputerCrafter

  • Moderators
  • 7,332 posts
  • LocationAustralia

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 by theoriginalbit, 17 March 2014 - 02:24 AM.


#9 skwerlman

  • Members
  • 163 posts
  • LocationPennsylvania

Posted 17 March 2014 - 07:20 AM

View Posttheoriginalbit, on 17 March 2014 - 02:24 AM, said:

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!





3 user(s) are reading this topic

0 members, 3 guests, 0 anonymous users