<p>没有“正确”的方法来做这件事,因为Lua并没有真正区分代码的来源,它们都只是函数。也就是说,这至少在Lua5.1中是可行的:</p>
<pre><code>matthew@silver:~$ cat hybrid.lua
if pcall(getfenv, 4) then
print("Library")
else
print("Main file")
end
matthew@silver:~$ lua hybrid.lua
Main file
matthew@silver:~$ lua -lhybrid
Library
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> ^C
matthew@silver:~$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require "hybrid"
Library
> ^C
matthew@silver:~$
</code></pre>
<p>它通过检查堆栈深度是否大于3(stock Lua解释器中文件的正常深度)来工作。但是,这个测试可能会在Lua版本之间中断,甚至在任何嵌入式/自定义Lua构建中也是如此。</p>
<p>我还将包括这个(稍微更便携的)替代方案,尽管它在启发式方面有了更大的飞跃,并且有一个失败案例(见下文):</p>
<pre><code>matthew@silver:~$ cat hybrid2.lua
function is_main(_arg, ...)
local n_arg = _arg and #_arg or 0;
if n_arg == select("#", ...) then
for i=1,n_arg do
if _arg[i] ~= select(i, ...) then
print(_arg[i], "does not match", (select(i, ...)))
return false;
end
end
return true;
end
return false;
end
if is_main(arg, ...) then
print("Main file");
else
print("Library");
end
matthew@silver:~$ lua hybrid2.lua
Main file
matthew@silver:~$ lua -lhybrid2
Library
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> ^C
matthew@silver:~$ lua
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
> require "hybrid2"
Library
>
</code></pre>
<p>这一个是通过比较G.arg的内容和“…”的内容来工作的。在主要部分,它们总是一样的。在模块中,G.arg仍将包含命令行参数,但“…”将包含传递给require()的模块名。我怀疑这更接近于更好的解决方案,因为你知道你的模块名。此代码中的错误在于用户使用1个参数执行主脚本时,这是模块的确切名称:</p>
<pre><code>matthew@silver:~$ lua -i hybrid2.lua hybrid2
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
Main file
> require "hybrid2"
Main file
>
</code></pre>
<p>鉴于以上情况,我希望至少你知道你的立场,即使这不是你所想的:)</p>
<p><strong>更新:</strong>对于在lua 5.1和5.2中工作的hybrid.lua版本,可以用debug.getlocal替换getfenv:</p>
<pre><code>if pcall(debug.getlocal, 4, 1) then
print("Library")
else
print("Main file")
end
</code></pre>