Reputation: 451
I'm loading a lua script that tries to import a secondary lua script. The issue is that I load the initial script (Main.lua) in C++ and specify a path to this Lua, then when the Main.lua tries to run dofile on "Other.lua" it can't find it...
I get...
cannot open Other.lua: No such file or directory
main.cpp
#include "sol.hpp"
int main()
{
sol::state m_lua;
m_lua.open_libraries(sol::lib::base);
sol::protected_function_result result = m_lua.script_file("../../../Desktop/Main.lua");
if (!result.valid())
{
sol::error err = result;
std::string what = err.what();
std::cout << "Failed to load script: Test.lua - " << what << std::endl;
}
}
}
Main.lua
print("Main Loaded");
dofile("Other.lua");
Other.lua - Stored in the same folder as "Main.lua"
print("Other Loaded");
Upvotes: 0
Views: 1972
Reputation: 344
If you're using LuaRocks, your configuration might have overriden lua's path default config, that will cause issues (it happens often, really)
There isn't any good guides about how to manage this, and as you get more advanced with Lua, you will face this kind of issues, so I had to write this for you and other people that might be experiencing these kind of issues.
There's many procedures you can take to fix this (nested relative imports can be pure madness)
You can simply assign the current path to package.path
package.path = package.path .. ';' .. ('./?.lua')
package.path = package.path .. ';' .. ('./?/init.lua')
.
is the current directory, and ?
gets replaced by the name of the script you passed to require()
, this way it will forcedly have to search in the current directory as well.
In some projects, you will have to manage importing from nested folders and even importing from folders behind
Lua makes it especially hard to manage imports, in example, if you used require
at a script which was already required from the root folder, you will have to index the script you want to load starting from the root folder
Instead of something like require(libs.classes.functions.public.dev.MyFunction)
you can also do this:
If the script is imported from an already nested script, you can use (...)
in the root of the script to get the path of imports (only in Lua 5.1 and above)
> current_path = (...)
will equal to the path of the current script based on the relative path (if the script is already nested)
It will return something similar to this:
root.lib.classes.currentscriptname
The last name will equal to the script name from where (...)
was used.
If you want to import from the script current folder, use (...):match('(.-)[^%.]+$')
, this will allow you to import from the current script parent directory, that is, the folder where the current script is located at, not where the main script is located at.
So:
BASE = (...):match('(.-)[^%.]+$')
and then require(BASE .. 'myLib')
will import myLib
from the folder that holds the current script.
In example, assuming you ran main.lua
, located at main/
, then imported a script which is called loader.lua
, located at main/lib/classes
, imagine you want to load two scripts:
main/lib
main/lib/classes
You can do the following:
At your main.lua script:
-- main.lua
-- From Lua 5.1 and above
-- Since this script is not nested
-- this will only contain the name of the current script (without '.lua'), which is "main"
local CURRENT_PATH = (...)
LIBS_PATH = CURRENT_PATH .. '.lib' -- This will hold "main.lib"
At your loader.lua script:
-- loader.lua
-- From Lua 5.1 and above
-- This will contain "main.lib.classes.", which already has a dot at the end
local CURRENT_PATH = (...):match('(.-)[^%.]+$')
-- SCRIPT_PATH will contain "main.lib.classes.loader"
local SCRIPT_PATH = (...)
-- Import from main/lib/assets.lua
local assets = require(LIB_PATH .. '.assets')
-- Import from current directory (main/lib/classes)
local bullet = require(BASE .. 'assets')
This will allow you to load both scripts from loader.lua
without much hassle and without making an unnecessarily long path.
Upvotes: 1
Reputation: 7046
Just pass Main.lua
the path where it should load the Other.lua
script from C++ and prepend that to the filename before passing it to dofile
in Lua.
Upvotes: 1