Posted 03 December 2012 - 04:14 PM
It would be handy if apis could 'set' the metatable of themselves, an example usage could be for the vector api where you could set the __call metamethod so that you could have a 'constructor'.
I have made an example os.loadAPI function, though this maybe isn't the best way to implement it is a proof of concept.
And a quick example api:
And using the example api:
– EDIT: Slightly sleeker implementation:
And example api:
And example usage:
I have made an example os.loadAPI function, though this maybe isn't the best way to implement it is a proof of concept.
Spoiler
local tAPIsLoading = {}
function os.loadAPI( _sPath )
local sName = fs.getName( _sPath )
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
if k ~= "__api_meta" then
tAPI[k] = v
end
end
local api_meta = rawget(tEnv, "__api_meta")
if api_meta ~= nil then
setmetatable(tAPI, api_meta)
end
_G[sName] = tAPI
tAPIsLoading[sName] = nil
return true
end
And a quick example api:
function hello()
print("Hello World!")
end
__api_meta = {
__call = function()
hello()
end
}
And using the example api:
os.loadAPI("helloAPI") -- Load the api
helloAPI.hello() -- Outputs "Hello World!"
helloAPI() -- Outputs "Hello World!"
print(tostring(helloAPI.__api_meta)) -- Outputs "nil", the metatable has been removed from the "public" api
– EDIT: Slightly sleeker implementation:
local tAPIsLoading = {}
function os.loadAPI( _sPath )
local sName = fs.getName( _sPath )
if tAPIsLoading[sName] == true then
printError( "API "..sName.." is already being loaded" )
return false
end
tAPIsLoading[sName] = true
local tEnv = {}
local api_meta = {}
setmetatable( tEnv, {
__index = function(t, k)
if k == "setapimeta" then
return function(_m)
api_meta = _m
end
elseif k == "getapimeta" then
return function()
return api_meta
end
else
return _G[k]
end
end
} )
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
setmetatable(tAPI, api_meta)
_G[sName] = tAPI
tAPIsLoading[sName] = nil
return true
end
And example api:
function hello()
print("Hello World!")
end
setapimeta({
__call = function()
hello()
end
})
for k, v in pairs(getapimeta()) do
print(k, " = ", v)
end -- Outputs "__call = function: #####"
And example usage:
os.loadAPI("helloAPI") -- Load the api
helloAPI.hello() -- Outputs "Hello World!"
helloAPI() -- Outputs "Hello World!"
Edited on 03 December 2012 - 03:50 PM