This is a read-only snapshot of the ComputerCraft forums,
taken in April 2020.
Os.loadapi() Find Path Of Loaded File
Started by Imred Gemu, 25 August 2013 - 09:07 PMPosted 25 August 2013 - 11:07 PM
I am writing program that can be used as either an API or as an executable and I need it to be able to find the absolute path to itself in both cases, I know that if I call shell.getRunningProgram() it will either return the name of the program if it is being executed or error out if it is being loaded, while this is helpful if it is being executed or for telling if it is being executed or loaded, I can't find the name of the program as it is being loaded this way because it errors out, and even if it didn't I assume it would just tell me the name of the program that loaded it based on my understanding of how the shell works. I don't want the person calling the api to have to tell my program where it is located so my question is, does anyone know how to find the absolute path to a program if it is being loaded with os.loadAPI() as opposed to being executed?
Posted 26 August 2013 - 01:32 AM
maybe try an overwrite of the function??? i personally havnt tried this myself(its in spoiler)
Spoiler
local tAPIsLoading = {}
os.loadAPI = function( _sPath ) -- overwrite the function
local sName = fs.getName( _sPath ) -- either change this to a global variable by removing local or add
filename = sName -- that you can later grab as a global variable
if tAPIsLoading[sName] == true then
printError( "API "..sName.." is already being loaded" )
return false
end
tAPIsLoading[sName] = true
local tEnv = {}
setmetatable( tEnv, { __index = _G } )
local fnAPI, err = loadfile( _sPath )
if fnAPI then
setfenv( fnAPI, tEnv )
fnAPI()
else
printError( err )
tAPIsLoading[sName] = nil
return false
end
local tAPI = {}
for k,v in pairs( tEnv ) do
tAPI[k] = v
end
_G[sName] = tAPI
tAPIsLoading[sName] = nil
return true
end
Posted 26 August 2013 - 01:45 AM
I think that jay5476 has the right idea, but perhaps overwriting the function in the bios.lua file isn't the best way to go about it. Instead, you might want to try overwriting the function at startup or sometime before you try to load your API. You could, for example, create a table to keep track of all APIs which are loaded properly
Off the top of my head, this is what I could come up with:
This way, if the api loads properly, the global table 'loadedAPIs' will contain a stack of the APIs which are loaded. When you load your API, you can check the element at loadedAPIs[#loadedAPIs] to get the path of your API.
NOTE: You might also want to overwrite os.unloadAPI to remove the elements from the table.
Off the top of my head, this is what I could come up with:
_G.loadedAPIs = {}
local oldOsLoadAPI = os.loadAPI
os.loadAPI = function (apiPath)
_G.loadedAPIs[#_G.loadedAPIs + 1] = apiPath
local success, errorMessage = pcall (oldOsLoadAPI, apiPath)
if not success then
_G.loadedAPIs[#_G.loadedAPIs] = nil
end
end
This way, if the api loads properly, the global table 'loadedAPIs' will contain a stack of the APIs which are loaded. When you load your API, you can check the element at loadedAPIs[#loadedAPIs] to get the path of your API.
NOTE: You might also want to overwrite os.unloadAPI to remove the elements from the table.
Posted 26 August 2013 - 02:05 AM
would of been better to do
oldLoad = os.loadApi
os.loadApi = function(path)
file = path
return oldLoad()
end
or with a table for all
apis = {}
oldLoad = os.loadAPI
os.loadAPI = function(path)
table.insert(apis, path)
return oldLoad()
end
and yes do unload to eg. (think this works)
oldUnload = os.unloadAPI
os.unloadAPI = function(path)
for k,v in pairs(apis) do
if v == path then
unloaded = k
end
end
table.remove(apis, unloaded)
return oldUnload()
end
wow howd i miss that :/ i also believe grims works tooPosted 26 August 2013 - 03:46 AM
Several answers had been given already, but whatever. I'd just create a new loadAPI and put it into _G. No messing with unloading.
function _G.os.loadAPIEx(path)
os.loadAPI(path)
local realName = fs.getName(path)
_G[realName]._path = path
end
That'll just put a _path variable into the API itself.You return oldLoad and oldUnload there, but don't call them. Most important part out.-snip-
Posted 26 August 2013 - 04:16 AM
Several answers had been given already, but whatever. I'd just create a new loadAPI and put it into _G. No messing with unloading.That'll just put a _path variable into the API itself.function _G.os.loadAPIEx(path) os.loadAPI(path) local realName = fs.getName(path) _G[realName]._path = path end
lolz you gotta local copy it or on line 2 you might end up with a out of bounds error
Posted 26 August 2013 - 04:18 AM
Nah. _G.os.loadAPIEx. That's what I mean by "new" os.loadAPI.Several answers had been given already, but whatever. I'd just create a new loadAPI and put it into _G. No messing with unloading.That'll just put a _path variable into the API itself.function _G.os.loadAPIEx(path) os.loadAPI(path) local realName = fs.getName(path) _G[realName]._path = path end
lolz you gotta local copy it or on line 2 you might end up with a out of bounds error
Posted 26 August 2013 - 04:31 AM
derp. I did not see that, my mistake
Posted 26 August 2013 - 12:34 PM
Was worried that would be most peoples answer, thanks for all your suggestions guys. I have a simpler work around that has less chances of conflicting with other programs who may also want to overwrite the default os.loadAPI(), while the work around is simpler than doing that, It would be a lot more complicated than using something similar to shell.getRunningProgram() except for loaded apis so I just wanted to ask if there was something like that, but since there isn't I'll just go with my alternative. Again thanks so much for all your suggestions!
Posted 26 August 2013 - 03:47 PM
If you have a more elegant solution please share it with us as many search the ask a pro forum before asking a question and your solution may help them
Posted 26 August 2013 - 07:49 PM
Unfortunately my alternative only solves the issue in my program that results from not being sure of it's path name, it doesn't allow me to find the path to my program.If you have a more elegant solution please share it with us as many search the ask a pro forum before asking a question and your solution may help them