The docs are here.

This commit is contained in:
ThePhD 2016-03-11 17:47:15 -05:00
parent c5e637c85b
commit 338278edf7
32 changed files with 2709 additions and 60 deletions

216
docs/Makefile Normal file
View File

@ -0,0 +1,216 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
.PHONY: help
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
.PHONY: clean
clean:
rm -rf $(BUILDDIR)/*
.PHONY: html
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
.PHONY: dirhtml
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
.PHONY: singlehtml
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
.PHONY: pickle
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
.PHONY: json
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
.PHONY: htmlhelp
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
.PHONY: qthelp
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Sol.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Sol.qhc"
.PHONY: applehelp
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
.PHONY: devhelp
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/Sol"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Sol"
@echo "# devhelp"
.PHONY: epub
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
.PHONY: latex
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
.PHONY: latexpdf
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: latexpdfja
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: text
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
.PHONY: man
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
.PHONY: texinfo
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
.PHONY: info
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
.PHONY: gettext
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
.PHONY: changes
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
.PHONY: linkcheck
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
.PHONY: doctest
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
.PHONY: coverage
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
.PHONY: xml
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
.PHONY: pseudoxml
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

263
docs/make.bat Normal file
View File

@ -0,0 +1,263 @@
@ECHO OFF
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set BUILDDIR=build
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source
set I18NSPHINXOPTS=%SPHINXOPTS% source
if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
)
if "%1" == "" goto help
if "%1" == "help" (
:help
echo.Please use `make ^<target^>` where ^<target^> is one of
echo. html to make standalone HTML files
echo. dirhtml to make HTML files named index.html in directories
echo. singlehtml to make a single large HTML file
echo. pickle to make pickle files
echo. json to make JSON files
echo. htmlhelp to make HTML files and a HTML help project
echo. qthelp to make HTML files and a qthelp project
echo. devhelp to make HTML files and a Devhelp project
echo. epub to make an epub
echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
echo. text to make text files
echo. man to make manual pages
echo. texinfo to make Texinfo files
echo. gettext to make PO message catalogs
echo. changes to make an overview over all changed/added/deprecated items
echo. xml to make Docutils-native XML files
echo. pseudoxml to make pseudoxml-XML files for display purposes
echo. linkcheck to check all external links for integrity
echo. doctest to run all doctests embedded in the documentation if enabled
echo. coverage to run coverage check of the documentation if enabled
goto end
)
if "%1" == "clean" (
for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
del /q /s %BUILDDIR%\*
goto end
)
REM Check if sphinx-build is available and fallback to Python version if any
%SPHINXBUILD% 1>NUL 2>NUL
if errorlevel 9009 goto sphinx_python
goto sphinx_ok
:sphinx_python
set SPHINXBUILD=python -m sphinx.__init__
%SPHINXBUILD% 2> nul
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
:sphinx_ok
if "%1" == "html" (
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
goto end
)
if "%1" == "dirhtml" (
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
goto end
)
if "%1" == "singlehtml" (
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
goto end
)
if "%1" == "pickle" (
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the pickle files.
goto end
)
if "%1" == "json" (
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can process the JSON files.
goto end
)
if "%1" == "htmlhelp" (
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run HTML Help Workshop with the ^
.hhp project file in %BUILDDIR%/htmlhelp.
goto end
)
if "%1" == "qthelp" (
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished; now you can run "qcollectiongenerator" with the ^
.qhcp project file in %BUILDDIR%/qthelp, like this:
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Sol.qhcp
echo.To view the help file:
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Sol.ghc
goto end
)
if "%1" == "devhelp" (
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
if errorlevel 1 exit /b 1
echo.
echo.Build finished.
goto end
)
if "%1" == "epub" (
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The epub file is in %BUILDDIR%/epub.
goto end
)
if "%1" == "latex" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
if errorlevel 1 exit /b 1
echo.
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdf" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "latexpdfja" (
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
cd %BUILDDIR%/latex
make all-pdf-ja
cd %~dp0
echo.
echo.Build finished; the PDF files are in %BUILDDIR%/latex.
goto end
)
if "%1" == "text" (
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The text files are in %BUILDDIR%/text.
goto end
)
if "%1" == "man" (
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The manual pages are in %BUILDDIR%/man.
goto end
)
if "%1" == "texinfo" (
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
goto end
)
if "%1" == "gettext" (
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
goto end
)
if "%1" == "changes" (
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
if errorlevel 1 exit /b 1
echo.
echo.The overview file is in %BUILDDIR%/changes.
goto end
)
if "%1" == "linkcheck" (
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
if errorlevel 1 exit /b 1
echo.
echo.Link check complete; look for any errors in the above output ^
or in %BUILDDIR%/linkcheck/output.txt.
goto end
)
if "%1" == "doctest" (
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
if errorlevel 1 exit /b 1
echo.
echo.Testing of doctests in the sources finished, look at the ^
results in %BUILDDIR%/doctest/output.txt.
goto end
)
if "%1" == "coverage" (
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
if errorlevel 1 exit /b 1
echo.
echo.Testing of coverage in the sources finished, look at the ^
results in %BUILDDIR%/coverage/python.txt.
goto end
)
if "%1" == "xml" (
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The XML files are in %BUILDDIR%/xml.
goto end
)
if "%1" == "pseudoxml" (
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
if errorlevel 1 exit /b 1
echo.
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
goto end
)
:end

View File

@ -0,0 +1,10 @@
compatibility.hpp
=================
Lua 5.3/5.2 compatibility for Lua 5.1/LuaJIT
--------------------------------------------
This is a detail header used to maintain compatability with the 5.2 and 5.3 APIs. It contains code from the MIT-Licensed `Lua<http://www.Lua.org/>` code in some places and also from the `lua-compat<https://github.com/keplerproject/lua-compat-5.3>` repository by KeplerProject.
It is not fully documented as this header's only purpose is for internal use to make sure Sol compiles across all platforms / distributions with no errors or missing Lua functionality. If you think there's some compatibility features we are missing or if you are running into redefinition errors, please make an `issue in the issue tracker<https://github.com/ThePhD/sol2/issues/>`.
For the licenses, see :doc:`here<../licenses>`

View File

@ -0,0 +1,103 @@
coroutine
=========
resumable/yielding functions from Lua
-------------------------------------
A ``coroutine`` is a :doc:`reference<reference>` to a function in Lua that can be called multiple times to yield a specific result. It is run on the :doc:`lua_State<state>` that was used to create it (see :doc:`thread<thread>` for an example on how to get a coroutine that runs on a thread separate from your usual "main" :doc:`lua_State<state>`).
The ``coroutine`` object is entirely similar to the :doc:`protected_function<protected_function>` object, with additional member functions to check if a coroutine has yielded (:doc:`call_status::yielded<types>`) and is thus runnable again, whether it has completed (:doc:`call_status::ok<types>`) and thus cannot yield anymore values, or whether it has suffered an error (see `status()` and :doc:`call_status<types>`'s error codes).
For example, you can work with a coroutine like this:
.. code-block:: lua
:caption: co.lua
function loop()
while counter ~= 30
do
coroutine.yield(counter);
counter = counter + 1;
end
return counter
end
This is a function that yields:
.. code-block:: cpp
:caption: main.cpp
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
lua.script_file("co.lua");
sol::coroutine cr = lua["loop"];
for (int counter = 0; // start from 0
counter < 10 && cr; // we want 10 values, and we only want to run if the coroutine "cr" is valid
// Alternative: counter < 10 && cr.valid()
++counter) {
// Call the coroutine, does the computation and then suspends
int value = cr();
}
Note that this code doesn't check for errors: to do so, you can call the function and assign it as ``auto result = cr();``, then check ``result.valid()`` as is the case with :doc:`protected_function<protected_function>`. Finally, you can run this coroutine on another thread by doing the following:
.. code-block:: cpp
:caption: main_with_thread.cpp
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::coroutine);
lua.script_file("co.lua");
sol::thread runner = sol::thread::create(lua.lua_state());
sol::state_view runnerstate = runner.state();
sol::coroutine cr = runnerstate["loop"];
for (int counter = 0; counter < 10 && cr; ++counter) {
// Call the coroutine, does the computation and then suspends
int value = cr();
}
The following are the members of ``sol::coroutine``:
members
-------
.. _status:
.. code-block:: cpp
:caption: returning the coroutine's status
call_status status() const noexcept;
Returns the status of a coroutine.
.. code-block:: cpp
:caption: checks for an error
bool error() const noexcept;
Checks if an error occured when the coroutine was run.
.. _runnable:
.. code-block:: cpp
:caption: runnable and explicit operator bool
bool runnable () const noexcept;
explicit operator bool() const noexcept;
These functions allow you to check if a coroutine can still be called (has more values to yield and has not errored). If you have a coroutine object ``coroutine my_co = /*...*/``, you can either check ``runnable()`` or do ``if ( my_co ) { /* use coroutine */ }``.
.. code-block:: cpp
:caption: calling a coroutine
template<typename... Args>
protected_function_result operator()( Args&&... args );
template<typename... Ret, typename... Args>
decltype(auto) call( Args&&... args );
template<typename... Ret, typename... Args>
decltype(auto) operator()( types<Ret...>, Args&&... args );
Calls the coroutine. The second ``operator()`` lets you specify the templated return types using the ``my_co(sol::types<int, std::string>, ...)`` syntax. Check :ref:`status()<status>` afterwards for more information about the success of the run or just check the coroutine object in an ifs tatement, as shown :ref:`above<runnable>`.

15
docs/source/api/error.rst Normal file
View File

@ -0,0 +1,15 @@
error
=====
the single exception type
-------------------------
.. code-block:: cpp
class error : public std::runtime_error {
public:
error(const std::string& str): std::runtime_error("Lua: error: " + str) {}
};
If an eror is thrown by Sol, it is going to be of this type. We use this in a single place: the default ``at_panic`` function we bind on construction of a :doc:`sol::state<state>`. If you turn :doc:`off exceptions<../exceptions>`, the chances of you seeing this error are :doc:`nil<types>`.
As it derives from ``std::runtime_error``, which derives from ``std::exception``, you can catch it with a ``catch (const std::exception& )`` clause in your try/catch blocks.

View File

@ -0,0 +1,52 @@
function
========
calling functions bound to Lua
------------------------------
.. code-block:: cpp
class function : public reference;
Function is a correct-assuming version of :doc:`protected_function<protected_function>`, omitting the need for typechecks and error handling. It is the default function type of Sol. When called without the return types being specified by either a ``sol::types<...>`` list or a ``call<Ret...>( ... )`` template type list, it generates a :doc:`function_result<proxy>` class that gets implicitly converted to the requested return type. For example:
.. code-block:: lua
:caption: func_barks.lua
:linenos:
bark_power = 11;
function woof ( bark_energy )
return (bark_energy * (bark_power / 4))
end
The following C++ code will call this function from this file and retrieve the return value:
.. code-block:: cpp
:linenos:
sol::state lua;
lua.script_file( "func_barks.lua" );
sol::function woof = lua["woof"];
double numwoof = woof(20);
The call ``woof(20)`` generates a :doc:`function_result<proxy>`, which is then implicitly converted to an ``double`` after being called. The intermediate temporary ``function_result`` is then destructed, popping the Lua function call results off the Lua stack.
.. warning::
Do NOT save the return type of a :doc:`function_result<proxy>` with ``auto``, as in ``auto numwoof = woof(20);``, and do NOT store it anywhere. Unlike its counterpart :doc:`protected_function_result<proxy>`, ``function_result`` is NOT safe to store as it assumes that its return types are still at the top of the stack and when its destructor is called will pop the number of results the function was supposed to return off the top of the stack. If you mess with the Lua stack between saving ``function_result`` and it being destructed, you will be subject to an incredible number of surprising and hard-to-track bugs. Don't do it.
.. code-block:: cpp
:caption: function: call operator / function call
template<typename... Args>
protected_function_result operator()( Args&&... args );
template<typename... Ret, typename... Args>
decltype(auto) call( Args&&... args );
template<typename... Ret, typename... Args>
decltype(auto) operator()( types<Ret...>, Args&&... args );
Calls the function. The second ``operator()`` lets you specify the templated return types using the ``my_func(sol::types<int, std::string>, ...)`` syntax. Function assumes there are no runtime errors, and thusly will call the ``atpanic`` function if an error does occur.

View File

@ -0,0 +1,45 @@
object
======
general-purpose safety reference to an existing object
------------------------------------------------------
.. code-block:: cpp
class object : reference;
``object``'s goal is to allow someone to pass around the most generic form of a reference to something in Lua (or propogate a ``nil``). It is the logical extension of :doc:`sol::reference<reference>`, and is used in :doc:`sol::table<table>`'s iterators.
members
-------
.. code-block:: cpp
:caption: function: type conversion
template<typename T>
decltype(auto) as() const;
Performs a cast of the item this reference refers to into the type ``T`` and returns it. It obeys the same rules as :doc:`sol::stack::get\<T><stack>`.
.. code-block:: cpp
:caption: function: type check
template<typename T>
bool is() const;
Performs a type check using the :doc:`sol::stack::check<stack>` api, after checking if the reference is valid.
non-members
-----------
.. code-block:: cpp
:caption: functions: nil comparators
bool operator==(const object& lhs, const nil_t&);
bool operator==(const nil_t&, const object& rhs);
bool operator!=(const object& lhs, const nil_t&);
bool operator!=(const nil_t&, const object& rhs);
These allow a person to compare an ``sol::object`` against ``nil``, which essentially checks if an object references a non-nil value, like so:

View File

@ -0,0 +1,87 @@
overload
========
calling different functions based on argument number/type
---------------------------------------------------------
this function helps users make overloaded functions that can be called from Lua using 1 name but multiple arguments. It is meant to replace the spaghetti of code whre users mock this up by doing strange if statemetns and switches on what version of a function to call based on `luaL_check{number/udata/string}<http://www.Lua.org/manual/5.3/manual.html#luaL_checkinteger>`. Its use is simple: whereever you can pass a function type to Lua, whether its on a :doc:`usertype<usertype>` or if you are just setting any kind of function with ``set`` or ``set_function`` (for :doc:`table<table>` or :doc:`state(_view)<state>`), simply wrap up the functions you wish to be considered for overload resolution on one function like so:
.. code-block:: cpp
sol::overload( func1, func2, ... funcN );
The functions can be any kind of function / function object (lambda). Given these functions and struct:
.. code-block:: cpp
:linenos:
struct pup {
int barks = 0;
void bark () {
++barks; // bark!
}
bool is_cute () const {
return true;
}
};
void ultra_bark( pup& p, int barks) {
for (; barks --> 0;) p.bark();
}
void picky_bark( pup& p, std::string s) {
if ( s == "bark" )
p.bark();
}
You then use it just like you would for any other part of the api:
.. code-block:: cpp
:linenos:
sol::state lua;
lua.set_function( "bark", sol::overload(
ultra_bark,
[]() { return "the bark from nowhere"; }
) );
lua.new_usertype<pup>( "pup",
// regular function
"is_cute", &pup::is_cute,
// overloaded function
"bark", sol::overloaded( &pup::bark, &ultra_bark )
);
Thusly, doing the following in Lua:
.. code-block:: Lua
:caption: pup.lua
:linenos:
local barker = pup.new()
pup.bark() -- calls member function pup::bark
pup.bark(20) -- calls ultra_bark
pup.bark("meow") -- picky_bark, no bark
pup.bark("bark") -- picky_bark, bark
bark(pup, 20) -- calls ultra_bark
local nowherebark = bark() -- calls lambda which returns that string
The actual class produced by ``sol::overload`` is essentially a type-wrapper around ``std::tuple`` that signals to the library that an overload is being created:
.. code-block:: cpp
:caption: function: create overloaded set
:linenos:
template <typename... Args>
struct overloaded_set : std::tuple<Args...> { /* ... */ };
template <typename... Args>
overloaded_set<Args...> overload( Args&&... args );
.. note::
Please keep in mind that doing this bears a runtime cost to find the proper overload. The cost scales directly not exactly with the number of overloads, but the number of functions that have the same argument count as each other (Sol will early-eliminate any functions that do not match the argument count).

View File

@ -0,0 +1,102 @@
protected_function
==================
Lua function calls that trap errors and provide error handler
-------------------------------------------------------------
.. code-block:: cpp
class protected_function : public reference;
Inspired by a request from `starwing<https://github.com/starwing>` in the old repository, this class provides the same interface as :doc:`function<function>` but with heavy protection and a potential error handler for any Lua errors and C++ exceptions. When called without the return types being specified by either a ``sol::types<...>`` list or a ``call<Ret...>( ... )`` template type list, it generates a :doc:`protected_function_result<proxy>` class that gets implicitly converted to the requested return type. For example:
.. code-block:: lua
:caption: pfunc_barks.lua
:linenos:
bark_power = 11;
function got_problems( error_msg )
return "got_problems handler: " .. error_msg
end
function woof ( bark_energy )
if bark_energy < 20
error("*whine*")
end
return (bark_energy * (bark_power / 4))
end
The following C++ code will call this function from this file and retrieve the return value:
.. code-block:: cpp
:linenos:
sol::state lua;
lua.open_file( "pfunc_barks.lua" );
sol::protected_function problematicwoof = lua["woof"];
problematicwoof.error_handler = lua["got_problems"];
auto firstwoof = problematic_woof(20);
if ( firstwoof.valid() ) {
// Can work with contents
double numwoof = first_woof;
}
else{
// An error has occured
std::string error = first_woof;
}
// errors, calls handler and then returns a string error from Lua at the top of the stack
auto secondwoof = problematic_woof(19);
if (secondwoof.valid()) {
// Call succeeded
double numwoof = firstwoof;
}
else {
// Call failed
// Note that if the handler was successfully called, this will include
// the additional appended error message information of
// "got_problems handler: " ...
std::string error = secondwoof;
}
This code is much more long-winded than its :doc:`function<function>` counterpart but allows a person to check for errors. The types here for ``auto`` are ``protected_function_result``. They are implicitly convertible to result types, like all :doc:`proxy-style<proxy>` types are.
members
-------
.. code-block:: cpp
:caption: function: call operator / protected function call
template<typename... Args>
protected_function_result operator()( Args&&... args );
template<typename... Ret, typename... Args>
decltype(auto) call( Args&&... args );
template<typename... Ret, typename... Args>
decltype(auto) operator()( types<Ret...>, Args&&... args );
Calls the function. The second ``operator()`` lets you specify the templated return types using the ``my_func(sol::types<int, std::string>, ...)`` syntax. If you specify no return type in any way, it produces s ``protected_function_result``.
.. code-block:: cpp
:caption: default handlers
static const reference& get_default_handler ();
static void set_default_handler( reference& ref );
Get and set the Lua entity that is used as the default error handler. The default is a no-ref error handler. You can change that by calling ``protected_function::set_default_handler( lua["my_handler"] );`` or similar: anything that produces a reference should be fine.
.. code-block:: cpp
:caption: variable: handler
reference error_handler;
The error-handler that is called should a runtime error that Lua can detect occurs. The error handler function needs to take a single string argument (use type std::string if you want to use a C++ function bound to lua as the error handler) and return a single string argument (again, return a std::string or string-alike argument from the C++ function if you're using one as the error handler). If :doc:`exceptions<../exceptions>` are enabled, Sol will attempt to convert the ``.what()`` argument of the exception into a string and then call the error handling function. It is a :doc:`reference<reference>`, as it must refer to something that exists in the lua registry or on the Lua stack. This is automatically set to the default error handler when ``protected_function`` is constructed.
.. note::
``protected_function_result`` safely pops its values off the stack when its destructor is called, keeping track of the index and number of arguments that were supposed to be returned. If you remove items below it using ``lua_remove``, for example, it will not behave as expected. Please do not perform fundamentally stack-rearranging operations until the destructor is called (pushing/popping above it is just fine).

158
docs/source/api/proxy.rst Normal file
View File

@ -0,0 +1,158 @@
proxy, (protected\_)function_result - proxy_base derivatives
============================================================
``table[x]`` and ``function(...)`` conversion struct
----------------------------------------------------
.. code-block:: c++
template <typename Recurring>
struct proxy_base;
template <typename Table, typename Key>
struct proxy : proxy_base<...>;
struct function_result : proxy_base<...>;
struct protected_function_result: proxy_base<...>;
These classes provide implicit ``operator=`` (``set``) and ``operator T`` (``get``) support for items retrieved from the underlying Lua implementation in Sol, specifically :doc:`sol::table<table>` and the results of function calls on :doc:`sol::function<function>` and :doc:`sol::protected_function<protected_function>`.
.. _proxy:
proxy
-----
``proxy`` is returned by lookups into :doc:`sol::table<table>` and table-like entities. Because it is templated on key and table type, it would be hard to spell: you can capture it using the word ``auto`` if you feel like you need to carry it around for some reason before using it. ``proxy`` evaluates its arguments lazily, when you finally call ``get`` or ``set`` on it. Here are some examples given the following lua script.
.. code-block:: lua
:linenos:
:caption: lua nested table script
bark = {
woof = {
[2] = "arf!"
}
}
After loading that file in or putting it in a string and reading the string directly in lua (see :doc:`state`), you can start kicking around with it in C++ like so:
.. code-block:: c++
:linenos:
sol::state lua;
// produces proxy, implicitly converts to std::string, quietly destroys proxy
std::string x = lua["bark"]["woof"][2];
``proxy`` lazy evaluation:
.. code-block:: c++
:linenos:
:caption: multi-get
auto x = lua["bark"];
auto y = x["woof"];
auto z = x[2];
// retrivies value inside of lua table above
std::string value = z; // "arf!"
// Can change the value later...
z = 20;
// Yay, lazy-evaluation!
int changed_value = z; // now it's 20!
We don't recommend the above to be used across classes or between function: it's more of something you can do to save a reference to a value you like, call a script or run a lua function, and then get it afterwards. You can also set functions (and function objects :ref:`*<note 1>`) this way, and retrieve them as well.
.. code-block:: c++
:linenos:
lua["bark_value"] = 24;
lua["chase_tail"] = floof::chase_tail; // chase_tail is a free function
members
-------
.. code-block:: c++
:caption: [overloaded] implicit conversion get
requires( sol::is_primitive_type<T>::value == true )
template <typename T>
operator T() const;
requires( sol::is_primitive_type<T>::value == false )
template <typename T>
operator T&() const;
Gets the value associated with the keys the proxy was generated and convers it to the type ``T``. Note that this function will always return ``T&``, a non-const reference, to types which are not based on :doc:`sol::reference<reference>` and not a :doc:`primitive lua type<types>`
.. code-block:: c++
:caption: [overloaded] implicit set
requires( sol::detail::Function<Fx> == false )
template <typename T>
proxy& operator=( T&& value );
requires( sol::detail::Function<Fx> == true )
template <typename Fx>
proxy& operator=( Fx&& function );
Sets the value associated with the keys the proxy was generated with to ``value``. If this is a function, calls ``set_function``. If it is not, just calls ``set``. See :ref:`note<note 1>`
.. code-block:: c++
template <typename Fx>
proxy& set_function( Fx&& fx );
Sets the value associated with the keys the proxy was generated with to a function ``fx``.
.. code-block:: c++
template <typename T>
T get( ) const;
Gets the value associated with the keys the proxy was generated and convers it to the type ``T``.
.. _note 1:
Note: Function Objects and proxies
----------------------------------
Consider the following:
.. code-block:: cpp
:linenos:
:caption: Note 1 Case
struct doge {
int bark;
void operator()() {
bark += 1;
}
};
sol::state lua;
lua["object"] = doge{}; // bind constructed doge to "object"
When you use the ``lua["object"] = doge{};`` from above, keep in mind that Sol detects if this is a function *callable with any kind of arguments*. If ``doge`` has overriden ``return_type operator()( argument_types... )`` on itself, it may result in satisfying the ``requires`` constraint from above. This means that if you have a user-defined type you want to bind as a :doc:`userdata with usertype semantics<usertype>` with this syntax, it might get bound as a function and not as a user-defined type. use ``lua["object"].set(doge)`` directly to avoid this, or ``lua["object"].set_function(doge{})`` to perform this explicitly.
.. _function_result:
function_result
---------------
``function_result`` is a temporary-only, intermediate-only implicit conversion worker for when :doc:`function<function>` is called. It is *NOT* meant to be stored or captured with ``auto``. It provides fast access to the desired underlying value. It does not implement ``set`` / templated ``operator=``.
.. _protected_function_result:
protected_function_result
-------------------------
``protected_function_result`` is a nicer version of ``function_result`` that can be used to detect errors. It sag\fe access to the desired underlying value. It does not implement ``set`` / templated ``operator=``.

View File

@ -0,0 +1,51 @@
reference
=========
general purpose reference to Lua object in registry
---------------------------------------------------
.. code-block:: cpp
:caption: reference
class reference;
This type keeps around a reference to something that was on the stack and places it in the Lua registry. It is the backbone for all things that reference items on the stack and needs to keep them around beyond their appearance and lifetime on said Lua stack. Its progeny include :doc:`sol::coroutine<coroutine>`, :doc:`sol::function<function>`, :doc:`sol::<protected_function>`, :doc:`sol::object<object>`, :doc:`sol::table<table>`/:doc:`sol::global_table<table>`, :doc:`sol::<thread>`, and :doc:`sol::userdata<userdata>`.
members
-------
.. code-block:: cpp
:caption: function: push referred-to element from the stack
int push() const noexcept;
This function pushes the referred-to data onto the stack and returns how many things were pushed. Typically, it returns 1.
.. code-block:: cpp
:caption: function: reference value
int registry_index() const noexcept;
The value of the reference in the registry.
.. code-block:: cpp
:caption: functions: non-nil, non-null check
bool valid () const noexcept;
explicit operator bool () const noexcept;
These functions check if the reference at ``T`` is valid: that is, if it is not :doc:`nil<types>` and if it is not non-existing (doesn't refer to anything, including nil) reference. The explicit operator bool allows you to use it in the context of an ``if ( my_obj )`` context.
.. code-block:: cpp
:caption: function: retrieves the type
type get_type() const noexcept;
Gets the :doc:`sol::type<types>` of the reference; that is, the Lua reference.
.. code-block:: cpp
:caption: function: lua_State* of the reference
lua_State* lua_state() const noexcept;
Gets the ``lua_State*`` this reference exists in.

View File

@ -0,0 +1,37 @@
resolve
=======
utility to pick overloaded C++ function calls
---------------------------------------------
.. code-block:: cpp
:caption: function: resolve C++ overload
template <typename... Args, typename F>
auto resolve( F f );
``resolve`` is a function that is meant to help users pick a single function out of a group of overloaded functions in C++. You can use it to pick overloads by specifying the signature as the first template argument. Given a collection of overloaded functions:
.. code-block:: cpp
:linenos:
int overloaded(int x);
int overloaded(int x, int y);
int overloaded(int x, int y, int z);
You can disambiguate them using ``resolve``:
.. code-block:: cpp
:linenos:
auto single = resolve<int(int)>( overloaded );
Note that this resolution is also built into ``set_function`` on :doc:`table<table>` and :doc:`state<state>`:
.. code-block:: cpp
:linenos:
sol::state lua;
lua.set_function<int(int)>("overloaded", overloaded);
lua.set_function<int(int, int)>("overloaded", overloaded);
lua.set_function<int(int, int, int)>("overloaded", overloaded);

132
docs/source/api/stack.rst Normal file
View File

@ -0,0 +1,132 @@
stack namespace
===============
the nitty-gritty core abstraction layer over Lua
------------------------------------------------
.. code-block:: cpp
namespace stack
If you find that the higher level abstractions are not meeting your needs, you may want to delve into the ``stack`` namespace to try and get more out of Sol. ``stack.hpp`` and the ``stack`` namespace define several utilities to work with Lua, including pushing / popping utilities, getters, type checkers, Lua call helpers and more. This namespace is not thoroughly documented as the majority of its interface is mercurial and subject to change between releases to either heavily boost performance or improve the Sol :doc:`api<top>`.
There are, however, a few :ref:`template customization points<extension_points>` that you may use for your purposes and a handful of potentially handy functions. These may help if you're trying to slim down the code you have to write, or if you want to make your types behave differently throughout the Sol stack. Note that overriding the defaults **can** throw out many of the safety guarantees Sol provides: therefore, modify the :ref:`extension points<extension_points>` at your own discretion.
functions
---------
.. code-block:: cpp
:caption: function: get
:name: stack-get
template <typename T>
auto get( lua_State* L, int index = -1 )
Retrieves the value of the object at ``index`` in the stack. The return type varies based on ``T``: with primitive types, it is usually ``T``: for all unrecognized ``T``, it is generally a ``T&`` or whatever the extension point :ref:`stack::getter\<T><getter>` implementation returns. The type ``T`` has top-level ``const`` qualifiers and reference modifiers removed before being forwarded to the extension point :ref:`stack::getter\<T><getter>` struct.
.. code-block:: cpp
:caption: function: check
template <typename T>
bool check( lua_State* L, int index = -1 )
template <typename T, typename Handler>
bool check( lua_State* L, int index, Handler&& handler )
Checks if the object at ``index`` is of type ``T``. If it is not, it will call the ``handler`` function with the index, expected, and actual types.
.. code-block:: cpp
:caption: function: push
// push T inferred from call site, pass args... through to extension point
template <typename T, typename... Args>
int push( lua_State* L, T&& item, Args&&... args )
// push T that is explicitly specified, pass args... through to extension point
template <typename T, typename Arg, typename... Args>
int push( lua_State* L, Arg&& arg, Args&&... args )
// recursively call the the above "push" with T inferred, one for each argument
template <typename... Args>
int multi_push( lua_State* L, Args&&... args )
Based on how it is called, pushes a variable amount of objects onto the stack. in 99% of cases, returns for 1 object pushed onto the stack. For the case of a ``std::tuple<...>``, it recursively pushes each object contained inside the tuple, from left to right, resulting in a variable number of things pushed onto the stack (this enables multi-valued returns when binding a C++ function to a Lua). Can be called with ``sol::stack::push<T>( L, args... )`` to have arguments different from the type that wants to be pushed, or ``sol::stack::push( L, arg, args... )`` where ``T`` will be inferred from ``arg``. The final form of this function is ``sol::stack::multi_push``, which will call one ``sol::stack::push`` for each argument. The ``T`` that describes what to push is first sanitized by removing top-level ``const`` qualifiers and reference qualifiers before being forwarded to the extension point :ref:`stack::pusher\<T><pusher>` struct.
.. code-block:: cpp
:caption: function: set_field
template <bool global = false, typename Key, typename Value>
void set_field( lua_State* L, Key&& k, Value&& v );
template <bool global = false, typename Key, typename Value>
void set_field( lua_State* L, Key&& k, Value&& v, int objectindex);
Sets the field referenced by the key ``k`` to the given value ``v``, by pushing the key onto the stack, pushing the value onto the stack, and then doing the equivalent of ``lua_setfield`` for the object at the given ``objectindex``. Performs optimizations and calls faster verions of the function if the type of ``Key`` is considered a c-style string and/or if its also marked by the templated ``global`` argument to be a global.
.. code-block:: cpp
:caption: function: get_field
template <bool global = false, typename Key>
void get_field( lua_State* L, Key&& k [, int objectindex] );
Gets the field referenced by the key ``k``, by pushing the key onto the stack, and then doing the equivalent of ``lua_getfield``. Performs optimizations and calls faster verions of the function if the type of ``Key`` is considered a c-style string and/or if its also marked by the templated ``global`` argument to be a global.
This function leaves the retrieved value on the stack.
.. _extension_points:
objects (extension points)
--------------------------
The structs below are already overriden for a handful of types. If you try to mess with them for the types ``sol`` has already overriden them for, you're in for a world of thick template error traces and headaches. Overriding them for your own user defined types should be just fine, however.
.. _getter:
.. code-block:: cpp
:caption: struct: getter
template <typename T, typename = void>
struct getter {
static T get (int index = -1) {
// ...
return // T, or something related to T.
}
};
This is an SFINAE-friendly struct that is meant to expose static function ``get`` that returns a ``T``, or something convertible to it. The default implementation assumes ``T`` is a usertype and pulls out a userdata from Lua before attempting to cast it to the desired ``T``. There are implementations for getting numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata_value<types>` and anything as upvalues with :doc:`upvalue_index<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``std::function<R(Args...)>``. It is also defined for anything that derives from :doc:`sol::reference<reference>`.
.. _pusher:
.. code-block:: cpp
:caption: struct: pusher
template <typename X, typename = void>
struct pusher {
template <typename T>
static int push ( lua_State* L, T&&, ... ) {
// can optionally take more than just 1 argument
// ...
return // number of things pushed onto the stack
}
};
This is an SFINAE-friendly struct that is meant to expose static function ``push`` that returns the number of things pushed onto the stack. The default implementation assumes ``T`` is a usertype and pushes a userdata into Lua with a :doc:`usertype_traits\<T><usertype>` metatable associated with it. There are implementations for pushing numbers (``std::is_floating``, ``std::is_integral``-matching types), getting ``std::string`` and ``const char*``, getting raw userdata with :doc:`userdata<types>` and raw upvalues with :doc:`upvalue<types>`, getting raw `lua_CFunction`_ s, and finally pulling out Lua functions into ``sol::function``. It is also defined for anything that derives from :doc:`sol::reference<reference>`.
.. code-block:: cpp
:caption: struct: checker
template <typename T, type expected = lua_type_of<T>, typename = void>
struct checker {
template <typename Handler>
static bool check ( lua_State* L, int index, Handler&& handler ) {
// if the object in the Lua stack at index is a T, return true
if ( ... ) return true;
// otherwise, call the handler function,
// with the required 4 arguments, then return false
handler(L, index, expected, indextype);
return false;
}
};
This is an SFINAE-friendly struct that is meant to expose static function ``check`` that returns the number of things pushed onto the stack. The default implementation simply checks whether the expected type passed in through the template is equal to the type of the object at the specified index in the Lua stack. The default implementation for types which are considered ``userdata`` go through a myriad of checks to support checking if a type is *actually* of type ``T`` or if its the base class of what it actually stored as a userdata in that index.
.. _lua_CFunction: http://www.Lua.org/manual/5.3/manual.html#lua_CFunction

75
docs/source/api/state.rst Normal file
View File

@ -0,0 +1,75 @@
state
=====
owning and non-owning state holders for registry and globals
------------------------------------------------------------
.. code-block:: cpp
class state_view;
class state : state_view, std::unique_ptr<lua_State*>;
The most important class here is ``state_view``. This structure takes a ``lua_State*`` that was already created and gives you simple, easy access to Lua's interfaces without taking ownership. ``state`` derives from ``state_view``, inheriting all of this functionality, but has the additional purpose of creating a fresh ``lua_State*`` and managing its lifetime for you in the default constructor.
The majority of the members between ``state_view`` and :doc:`sol::table<table>` are identical, with added for this higher-level type. Therefore, all of the examples and notes in :doc:`sol::table<table>` apply here as well.
enumerations
------------
.. _libenum:
.. code-block:: cpp
:caption: in-lua libraries
enum class lib : char {
base,
package,
coroutine,
string,
os,
math,
table,
debug,
bit32,
io,
count // do not use
};
This enumeration details the various base libraries that come with Lua. See the `standard lua libraries`_ for details about the various standard libraries.
members
-------
.. code-block:: cpp
:caption: function: open standard libraries/modules
template<typename... Args>
void open_libraries(Args&&... args);
This function takes a number of :ref:`sol::lib<libenum>` as arguments and opens up the associated Lua core libraries.
.. code-block:: cpp
:caption: function: script / script_file
void script(const std::string& code);
void script_file(const std::string& filename);
These functions run the desired blob of either code that is in a string, or code that comes from a filename, on the ``lua_State*``.
.. code-block:: cpp
:caption: function: global table / registry table
global_table globals() const;
table registry() const;
Get either the global table or the Lua registry as a :doc:`sol::table<table>`, which allows you to modify either of them directly. Note that getting the global table from a ``state``/``state_view`` is usually unnecessary as it has all the exact same functions as a :doc:`sol::table<table>` anyhow.
.. code-block:: cpp
:caption: function: Lua set_panic
void set_panic(lua_CFunction panic);
Overrides the panic function Lua calls when something unrecoverable or unexpected happens in the Lua VM. Must be a function of the that matches the ``int(*)(lua_State*)`` function signature.
.. _standard lua libraries: http://www.lua.org/manual/5.2/manual.html#6

115
docs/source/api/table.rst Normal file
View File

@ -0,0 +1,115 @@
table
=====
a representation of a Lua (meta)table
-------------------------------------
.. code-block:: cpp
template <bool global>
class table_core;
typedef table_core<false> table;
typedef table_core<true> global_table;
``sol::table`` is an extremely efficient manipulator of state that brings most of the magic of the Sol abstraction. Capable of doing multiple sets at once, multiple gets into a ``std::tuple``, being indexed into using ``[key]`` syntax and setting keys with a similar syntax (see: :doc:`here<proxy>`), ``sol::table`` is the corner of the interaction between Lua and C++.
There are two kinds of tables: the global table and non-global tables: however, both have the exact same interface and all ``sol::global_table`` s are convertible to regular ``sol::table`` s.
Tables are the core of Lua, and they are very much the core of Sol.
members
-------
.. code-block:: cpp
:caption: function: get / traversing get
template<typename... Args, typename... Keys>
decltype(auto) get(Keys&&... keys) const;
template<typename T, typename... Keys>
decltype(auto) traverse_get(Keys&&... keys) const;
These functions retrieve items from the table. The first one (``get``) can pull out *multiple* values, 1 for each key value passed into the function. In the case of multiple return values, it is returned in a ``std::tuple<Args...>``. It is similar to doing ``return table["a"], table["b"], table["c"]``. Because it returns a ``std::tuple``, you can use ``std::tie`` on a multi-get to retrieve all of the necessary variables. The second one (``traverse_get``) pulls out a *single* value, using each successive key provided to do another lookup into the last. It is similar to doing ``x = table["a"]["b"]["c"][...]``.
.. code-block:: cpp
:caption: function: set / traversing set
template<typename... Args>
table& set(Args&&... args);
template<typename... Args>
table& traverse_set(Args&&... args);
These functions set items into the table. The first one (``set``) can set *multiple* values, in the form ``Key, Value, Key, Value, ...``. It is similar to ``table["a"] = 1; table["b"] = 2, ...``. The second one (``traverse_set``) sets a *single* value, using all but the last argument as keys to do another lookup into the value retrieved prior to it. It is equivalent to ``table["a"]["b"][...] = final_value;``.
.. code-block:: cpp
:caption: function: setting a usertype
template<typename Class, typename... Args>
table& new_usertype(const std::string& name, Args&&... args);
template<typename Class, typename CTor0, typename... CTor, typename... Args>
table& new_usertype(const std::string& name, Args&&... args);
template<typename Class, typename... CArgs, typename... Args>
table& new_usertype(const std::string& name, constructors<CArgs...> ctor, Args&&... args);
This class of functions creates a new :doc:`usertype<usertype>` with the specified arguments, providing a few extra details for constructors. After creating a usertype with the specified argument, it passes it to :ref:`set_usertype<set_usertype>`.
.. _set_usertype:
.. code-block:: cpp
:caption: function: setting a pre-created usertype
template<typename T>
table& set_usertype(usertype<T>& user);
template<typename Key, typename T>
table& set_usertype(Key&& key, usertype<T>& user);
Sets a previously created usertype with the specified ``key`` into the table. Note that if you do not specify a key, the implementation falls back to setting the usertype with a ``key`` of ``usertype_traits<T>::name``, which is an implementation-defined name that tends to be of the form ``{namespace_name 1}_[{namespace_name 2 ...}_{class name}``.
.. code-block:: cpp
:caption: function: begin / end for iteration
table_iterator begin () const;
table_iterator end() const;
table_iterator cbegin() const;
table_iterator cend() const;
Provides `input iterators`_ for a table. This allows tables to work with single-pass, input-only algorithms (like ``std::for_each``).
.. code-block:: cpp
:caption: function: iteration with a function
template <typename Fx>
void for_each(Fx&& fx);
A functional ``for_each`` loop that calls the desired function. The passed in function must take either ``sol::object key, sol::object value`` or take a ``std::pair<sol::object, sol::object> key_value_pair``. This version can be a bit safer as allows the implementation to definitively pop the key/value off the Lua stack after each call of the function.
.. code-block:: cpp
:caption: function: operator[] access
template<typename T>
proxy<table&, T> operator[](T&& key);
template<typename T>
proxy<const table&, T> operator[](T&& key) const;
Generates a :doc:`proxy<proxy>` that is templated on the table type and the key type. Enables lookup of items and their implicit conversion to a desired type.
.. code-block:: cpp
:caption: function: set a function with the specified key into lua
template<typename Key, typename Fx>
state_view& set_function(Key&& key, Fx&& fx, [...]);
Sets the desired function to the specified key value. Note that it also allows for passing a member function plus a member object: however, using a lambda is almost always better when you want to bind a member function + class instance to a single function call in Lua.
.. code-block:: cpp
:caption: function: create a table with defaults
static table create(lua_State* L, int narr = 0, int nrec = 0);
template <typename Key, typename Value, typename... Args>
static table create(lua_State* L, int narr, int nrec, Key&& key, Value&& value, Args&&... args);
Creates a table, optionally with the specified values pre-set into the table. If ``narr`` or ``nrec`` are 0, then compile-time shenanigans are used to guess the amount of array entries (e.g., integer keys) and the amount of hashable entries (e.g., all other entries).
.. _input iterators: http://en.cppreference.com/w/cpp/concept/InputIterator

View File

@ -0,0 +1,43 @@
thread
======
a separate state that can contain and run functions
---------------------------------------------------
.. code-block:: cpp
class thread : public reference { /* ... */ };
``sol::thread`` is a separate runnable part of the Lua VM that can be used to execute work separately from the main thread, such as with :doc:`coroutines<coroutine>`. To take a table or a coroutine and run it specifically on the ``sol::thread`` you either pulled out of lua or created, just get that function through the :ref:`state of the thread<thread_state>`
members
-------
.. code-block:: cpp
:caption: function: view into thread_state()'s state
state_view state() const;
This retrieves the current state of the thread, producing a :doc:`state_view<state>` that can be manipulated like any other. :doc:`Coroutines<coroutine>` pulled from Lua using the thread's state will be run on that thread specifically.
.. _thread_state:
.. code-block:: cpp
:caption: function: retrieve thread state object
lua_State* thread_state () const;
This function retrieves the ``lua_State*`` that represents the thread.
.. code-block:: cpp
:caption: current thread status
thread_status status () const;
Retrieves the :doc:`thread status<types>` that describes the current state of the thread.
.. code-block:: cpp
:caption: thread creation
static thread create (lua_State* L);
Creates a new thread from the given a ``lua_State*``.

29
docs/source/api/top.rst Normal file
View File

@ -0,0 +1,29 @@
api reference manual
====================
Browse the various function and classes :doc:`Sol<../index>` utilizes to make your life easier when working with Lua.
.. toctree::
:caption: Sol API
:name: apitoc
:maxdepth: 1
compatibility
coroutine
error
function
protected_function
object
overload
proxy
reference
resolve
stack
state
table
thread
types
usertype
userdata

190
docs/source/api/types.rst Normal file
View File

@ -0,0 +1,190 @@
types
=====
nil, lua_primitive type traits, and other fundamentals
------------------------------------------------------
The ``types.hpp`` header contains various fundamentals and utilities of Sol.
enumerations
------------
.. code-block:: cpp
:caption: syntax of a function called by Lua
enum class call_syntax {
dot = 0,
colon = 1
};
This enumeration indicates the syntax a function was called with in a specific scenario. There are two ways to call a function: with ``obj:func_name( ... )`` or ``obj.func_name( ... );`` The first one passes "obj" as the first argument: the second one does not. In the case of usertypes, this is used to determine whether the call to a :doc:`constructor/initializer<usertype>` was called with a ``:`` or a ``.``, and not misalign the arguments.
.. _call_status:
.. code-block:: cpp
:caption: status of a Lua function call
enum class call_status : int {
ok = LUA_OK,
yielded = LUA_YIELD,
runtime = LUA_ERRRUN,
memory = LUA_ERRMEM,
handler = LUA_ERRERR,
gc = LUA_ERRGCMM
};
This strongly-typed enumeration contains the errors potentially generated by a call to a :doc:`protected function<protected_function>` or a :doc:`coroutine<coroutine>`.
.. _thread_status:
.. code-block:: cpp
:caption: status of a Lua thread
enum class thread_status : int {
normal = LUA_OK,
yielded = LUA_YIELD,
error_runtime = LUA_ERRRUN,
error_memory = LUA_ERRMEM,
error_gc = LUA_ERRGCMM,
error_handler = LUA_ERRERR,
dead,
};
This enumeration contains the status of a thread. The ``thread_status::dead`` state is generated when the thread has nothing on its stack and it is not running anything.
.. _type:
.. code-block:: cpp
:caption: type enumeration
enum class type : int {
none = LUA_TNONE,
nil = LUA_TNIL,
string = LUA_TSTRING,
number = LUA_TNUMBER,
thread = LUA_TTHREAD,
boolean = LUA_TBOOLEAN,
function = LUA_TFUNCTION,
userdata = LUA_TUSERDATA,
lightuserdata = LUA_TLIGHTUSERDATA,
table = LUA_TTABLE,
poly = none | nil | string | number | thread |
table | boolean | function | userdata | lightuserdata
};
The base types that Lua natively communicates in and understands. Note that "poly" isn't really a true type, it's just a symbol used in Sol for something whose type hasn't been checked (and you should almost never see it).
type traits
-----------
.. code-block:: cpp
:caption: lua_type_of trait
template <typename T, typename = void>
struct lua_type_of;
This type trait maps a C++ type to a :ref:`type enumation<type>` value. The default value is ``type::userdata``.
.. code-block:: cpp
:caption: primitive checking traits
template <typename T>
struct is_lua_primitive;
template <typename T>
struct is_proxy_primitive;
This trait is used by :doc:`proxy<proxy>` to know which types should be returned as references to internal Lua memory (e.g., ``userdata`` types) and which ones to return as values (strings, numbers, :doc:`references<reference>`). ``std::reference_wrapper``, ``std::tuple<...>`` are returned as values, but their contents are/can be references. The default value is false.
.. nil:
special types
-------------
.. code-block:: cpp
:caption: nil
strunil_t {};
const nil_t nil {};
bool operator==(nil_t, nil_t);
bool operator!=(nil_t, nil_t);
``nil`` is a constant used to signify Lua's ``nil``, which is a type and object that something does not exist. It is comparable to itself, :doc:`sol::object<object>` and :doc:`proxy values<proxy>`.
.. code-block:: cpp
:caption: non_null
template <typename T>
struct non_null {};
A tag type that, when used with :doc:`stack::get\<non_null\<T*>><stack>`, does not perform a ``nil`` check when attempting to retrieve the userdata pointer.
.. code-block:: cpp
:caption: type list
template <typename... Args>
struct types;
A type list that, unlike ``std::tuple<Args...>``, does not actually contain anything. Used to indicate types and groups of types all over Sol.
functions
---------
.. code-block:: cpp
:caption: type_of
template<typename T>
type type_of();
type type_of(lua_State* L, int index);
These functions get the type of a C++ type ``T`` or the type at the specified index on the Lua stack.
.. code-block:: cpp
:caption: type checking convenience functions
int type_panic(lua_State* L, int index, type expected, type actual);
int no_panic(lua_State*, int, type, type) noexcept;
void type_error(lua_State* L, int expected, int actual);
void type_error(lua_State* L, type expected, type actual);
void type_assert(lua_State* L, int index, type expected, type actual);
void type_assert(lua_State* L, int index, type expected);
.. code-block:: cpp
:caption: type name retrieval
std::string type_name(lua_State*L, type t);
Gets the Lua-specified name of the :ref:`type<type>`.
structs
-------
.. code-block:: cpp
struct userdata_value {
void* value;
};
struct light_userdata_value {
void* value;
};
struct up_value_index {
int index;
};
Types that differentiate between the two kinds of ``void*`` Lua hands back from its API: full userdata and light userdata, as well as a type that modifies the index passed to ``get`` to refer to `up values`_ These types can be used to trigger different underlying API calls to Lua when working with :doc:`stack<stack>` namespace and the ``push``/``get``/``pop``/``check`` functions.
.. _up values: http://www.Lua.org/manual/5.3/manual.html#4.4

View File

@ -0,0 +1,13 @@
userdata
===========
reference to a userdata
-----------------------
.. code-block:: cpp
:caption: (light\_)userdata reference
class userdata : public reference;
class light_userdata : public reference;
These type is meant to hold a reference to a (light) userdata from Lua and make it easy to push an existing userdata onto the stack. It is essentially identical to :doc:`reference<reference>` in every way, just with a definitive C++ type.

View File

@ -0,0 +1,252 @@
usertype<T>
===========
structures and classes from C++ made available to Lua code
----------------------------------------------------------
*Note: ``T`` refers to the type being turned into a usertype.*
While other frameworks extend lua's syntax or create Data Structure Languages (DSLs) to create classes in lua, :doc:`sol<../index>` instead offers the ability to generate easy bindings. These use metatables and userdata in lua for their implementation. Given this C++ class:
.. code-block:: cpp
:linenos:
struct ship {
int bullets = 20;
int life = 100;
bool shoot () {
if (bullets > 0) {
--bullets;
// successfully shot
return true;
}
// cannot shoot
return false;
}
bool hurt (int by) {
life -= by;
// have we died?
return life < 1;
}
};
You can bind the it to lua using the following C++ code:
.. code-block:: cpp
:linenos:
sol::state lua;
lua.new_usertype<ship>( "ship", // the name of the class, as you want it to be used in lua
// List the member functions you wish to bind:
// "name_of_item", &class_name::function_or_variable
"shoot", &ship::shoot,
"hurt", &ship::hurt,
// bind variable types, too
"life", &ship::bullets
// names in lua don't have to be the same as C++,
// but it probably helps if they're kept the same,
// here we change it just to show its possible
"bullet_count", &ship::bullets
);
Equivalently, you can also write:
.. code-block:: cpp
:linenos:
:emphasize-lines: 4,12
sol::state lua;
// Use constructor directly
usertype<ship> shiptype(
"shoot", &ship::shoot,
"hurt", &ship::hurt,
"life", &ship::bullets
"bullet_count", &ship::bullets
);
// set usertype explicitly, with the given name
lua.set_usertype<ship>( "ship", shiptype );
// shiptype is now a useless skeleton type, just let it destruct naturally and don't use it again.
Note that here, because the C++ class is default-constructible, it will automatically generate a creation function that can be called in lua called "new" that takes no arguments. You can use it like this in lua code:
.. code-block:: lua
:linenos:
fwoosh = ship.new()
local success = fwoosh:shoot() -- note the ":" that is there: this is mandatory for member function calls
local is_dead = fwoosh:hit(20)
-- check if it works
print(is_dead) -- the ship is not dead at this point
print(fwoosh.life .. "life left") -- 80 life left
print(fwoosh.bullet_count) -- 19
There are more advanced use cases for how to create and use a usertype, which are all based on how to use its constructor (see below).
enumerations
------------
.. _meta_function_enum:
.. code-block:: cpp
:caption: meta_function enumeration for names
:linenos:
enum class meta_function {
construct,
index,
new_index,
mode,
call,
metatable,
to_string,
length,
unary_minus,
addition,
subtraction,
multiplication,
division,
modulus,
power_of,
involution = power_of,
concatenation,
equal_to,
less_than,
less_than_or_equal_to,
garbage_collect,
call_function,
};
Use this enumeration to specify names in a manner friendlier than memorizing the special lua metamethod names for each of these. Each binds to a specific operation indicated by the descriptive name of the enum.
members
-------
.. code-block:: cpp
:caption: usertype<T> constructor
template<typename... Args>
usertype<T>(Args&&... args);
The constructor of usertype takes a variable number of arguments. It takes an even number of arguments (except in the case where the very first argument is passed as the :ref:`constructor<constructor>` or in the case of specifying a custom :ref:`destructor<destructor>`). Names can either be strings, :ref:`special meta_function enumerations<meta_function_enum>`, or one of the special indicators for initializers.
.. _constructor:
* ``"{name}", constructors<Type-List-0, Type-List-1, ...>``
- ``Type-List-N`` must be a ``sol::types<Args...>``, where ``Args...`` is a list of types that a constructor takes. Supports overloading by default
- If you pass the ``constructors<...>`` argument first when constructing the usertype, then it will automatically be given a ``"{name}"`` of ``"new"``
* ``"{name}", initializers( func1, func2, ... )``
- Creates initializers that, given one or more functions, provides an overloaded lua function for creating a the specified type.
+ The function must have the argument signature ``func T*, Arguments... )`` or ``func( T&, Arguments... )``, where the pointer or reference will point to a place of allocated memory that has an unitialized ``T``. Note that lua controls the memory.
.. _destructor:
* ``"__gc", sol::destructor( func )`` or ``sol::meta_function::garbage_collect, sol::destructor( func )``
- Creates a custom destructor that takes an argument ``T*`` or ``T&`` and expects it to be destructed/destroyed. Note that lua controls the memory and thusly will deallocate the necessary space AFTER this function returns (e.g., do not call ``delete`` as that will attempt to deallocate memory you did not ``new``).
- If you just want the default constructor, you can replace the second argument with ``sol::default_destructor``.
- The usertype will throw if you specify a destructor specifically but do not map it to ``sol::meta_function::gc`` or a string equivalent to ``"__gc"``.
* ``"{name}", &free_function``
- Binds a free function / static class function / function object (lambda) to ``"{name}"``. The first argument must be ``T*`` or ``T&`` in this case.
* ``"{name}", &type::function_name`` or ``"{name}", &type::member_variable``
- Binds a typical member function or variable to ``"{name}"``. In the case of a member variable or member function, ``type`` must be ``T`` or a base of ``T``.
* ``sol::base_classes, sol::bases<Bases...>``
- Tells a usertype what its base classes are. If you have exceptions turned on, this need not be necessary: if you do not then you need this to have derived-to-base conversions work properly. See :ref:`inheritance<usertype_inheritance>`.
overloading
-----------
Functions set here support overloading. See :doc:`here<overload>` for an example.
.. _usertype_inheritance:
inheritance
-----------
Sol can adjust pointers from derived classes to base classes at runtime, but it has some caveats based on what you compile with:
.. _exceptions_enabled:
**With Exceptions Enabled**
You do not need to manually specify the base classes. We use a technique that infinitely scales and automatically casts derived pointers to their base classes by exploiting the necessity of exception type matching.
.. _exceptions_disabled:
**With Exceptions Disabled**
You must specify the ``sol::base_classes`` tag with the ``sol::bases<Types...>()`` argument, where ``Types...`` are all the base classes of the single type ``T`` that you are making a usertype out of. when you create the usertype. If you turn exceptions off and are also completely mad and turn off :doc:`run-time type information<../rtti>` as well, we fallback to a id-based systemthat still requires you to specifically list the base classes as well. For example:
.. code-block:: cpp
:linenos:
struct A {
int a = 10;
virtual int call() { return 0; }
};
struct B : A {
int b = 11;
virtual int call() { return 20; }
};
Then, to register the base classes explicitly:
.. code-block:: cpp
:linenos:
:emphasize-lines: 5,6
sol::state lua;
lua.new_usertype<B>( "B",
"call", &B::call,
// List bases explicitly if you disable exceptions
sol::base_classes, sol::bases<A>()
);
Note that Sol does not support down-casting from a base class to a derived class at runtime.
inheritance + overloading
-------------------------
While overloading is supported regardless of `inheritance<inheritance>` caveats or not, the current version of Sol has a first-match, first-call style of overloading when it comes to inheritance. Put the functions with the most derived arguments first to get the kind of matching you expect.
.. todo::
Later versions of Sol will introduce a kind of overload resolution system that will rank overloads and call the best one, which will unfortunately come at a small performance penalty if you explicitly use overloads of many functions that have the same arity (argument count).
traits
------
.. code-block:: cpp
:caption: usertype_traits<T>
:linenos:
template<typename T>
struct usertype_traits {
static const std::string name;
static const std::string metatable;
static const std::string variable_metatable;
static const std::string gc_table;
};
This trait is used to provide names for the various metatables and global tables used to perform cleanup and lookup. They are automatically generated at runtime. In the case of RTTI being present, Sol will attempt to demangle the name from ``std::type_info`` to produce a valid name. If RTTI is disabled, Sol attempts to parse the output of ``__PRETTY_FUCNTION__`` (``g++``/``clang++``) or ``_FUNCDSIG`` (``vc++``) to get the proper type name. If you have a special need you can override the names for your specific type.
performance note
----------------
.. note::
Note that performance for member function calls goes down by a fixed overhead if you also bind variables as well as member functions. This is purely a limitation of the lua implementation and there's, unfortunately, nothing that can be done about it. If you bind only functions and no variables, however, Sol will automatically optimize the lua runtime and give you the maximum performance possible. *Please consider ease of use and maintenance of code before you make everything into functions.*

View File

@ -0,0 +1,18 @@
benchmarks
==========
because somebody is going to ask eventually...
----------------------------------------------
These are some informal and formal benchmarks done by both the developers of sol and other library developers / users. We leave you to interpret the data as you see fit.
* `lua_binding_benchmarks`_ by satoren (developer of `kaguya`_) (`Sol`_ is the "sol2" entry)
* `lua-bench`_ by ThePhD (developer of `Sol`_)
As of the writing of this documentation (March 11th, 2016), :doc:`Sol<index>` (Sol2) seems to take the cake in most categories for speed!
.. _lua-bench: https://github.com/ThePhD/lua-bench
.. _lua_binding_benchmarks: http://satoren.github.io/lua_binding_benchmark/
.. _kaguya: https://github.com/satoren/kaguya
.. _Sol: https://github.com/ThePhD/sol2

291
docs/source/conf.py Normal file
View File

@ -0,0 +1,291 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Sol documentation build configuration file, created by
# sphinx-quickstart on Mon Feb 29 21:49:51 2016.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx.ext.doctest',
'sphinx.ext.todo'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = 'Sol'
copyright = '2016, ThePhD'
author = 'ThePhD'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '2.0.0'
# The full version, including alpha/beta/rc tags.
release = '2.0.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# The default highlighting language: default is python
highlight_language = 'c++'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'Soldoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'Sol.tex', 'Sol Documentation',
'ThePhD', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'sol', 'Sol Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'Sol', 'Sol Documentation',
author, 'Sol', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False

View File

@ -0,0 +1,30 @@
exceptions
==========
since somebody is going to ask about it...
------------------------------------------
Yes, you can turn off exceptions in Sol with ``#define SOL_NO_EXCEPTIONS`` before including or by passing the command line argument that defines ``SOL_NO_EXCEPTIONS``. We don't recommend it unless you're playing with a Lua distro that also doesn't play nice with exceptions (like non-x64 versions of :ref:`LuaJIT<LuaJIT and exceptions>` ).
If you turn this off, the default `at_panic<http://www.Lua.org/manual/5.3/manual.html#4.6>` function :doc:`state<api/state>` set for you will not throw. Instead, the default Lua behavior of aborting will take place (and give you no chance of escape unless you implement your own at_panic function and decide to try ``longjmp`` out).
Note that this will also disable :doc:`protected_function<api/protected_function>`'s ability to catch C++ errors you throw from C++ functions bound to Lua that you are calling through that API. So, only turn off exceptions in Sol if you're sure you're never going to use them ever. Of course, if you are ALREADY not using Exceptions, you don't have to particularly worry about this and now you can use Sol!
If there is a place where a throw statement is called or a try/catch is used and it is not hidden behind a ``#ifndef SOL_NO_EXCEPTIONS`` block, please file an issue at `issue`_ or submit your very own pull request so everyone can benefit!
inheritance
-----------
Sol uses a nifty feature of exceptions to perform infinitely scaling, compiler-correct casting of derived pointers to their base classes. If you disable this and you want to have a :doc:`user-defined type<api/usertype>` that can be used with functions that take its base class or similar, you must specify those base classes manually using the :doc:`base_classes<api/usertype>` tag with the :doc:`bases\<Types...><api/usertype>` arguments when you create the usertype. If you turn exceptions off and are also completely mad and turn off :doc:`run-time type information<rtti>` as well, we fallback to a id-based base class system that still requires you to specifically list the base classes using the method mentioned previously. But if you have already turned off rtti and exceptions, you must really know what you're doing, so you should be just fine!
.. _LuaJIT and exceptions:
LuaJIT and exceptions
---------------------
It is important to note that a popular 5.1 distribution of Lua, LuaJIT, has some serious `caveats regarding exceptions<http://luajit.org/extensions.html#exceptions>`. LuaJIT's exception promises are flaky at best on x64 (64-bit) platforms, and entirely terrible on non-x64 (32-bit, ARM, etc.) platorms. The trampolines we have in place for all functions bound through conventional means in Sol will catch exceptions and turn them into Lua errors so that LuaJIT remainds unperturbed, but if you link up a C function directly yourself and throw, chances are you might have screwed the pooch.
Testing in `this closed issue<https://github.com/ThePhD/sol2/issues/28>` reveals that it doesn't play nice on 64-bit Linux in many cases either, especially when it hits an error internal to the interpreter (and does not go through Sol). We do have tests, however, that compile for our continuous integration check-ins that check this functionality across several compilers and platforms to keep you protected and given hard, strong guarantees for what happens if you throw in a function bound by Sol. If you stray outside the realm of Sol's protection, however... Good luck.
.. _issue: https://github.com/ThePhD/sol2/issues/

168
docs/source/features.rst Normal file
View File

@ -0,0 +1,168 @@
features
========
what does Sol (and other libraries) support?
--------------------------------------------
The goal of Sol is to provide an incredibly clean API that provides high performance (comparable or better than the C it was written on) and extreme ease of use. That is, users should be able to say: "this works pretty much how I expected it to."
For the hard technical components of Lua and its ecosystem we support, here is the full rundown:
what Sol supports
-----------------
* Support for Lua 5.1, 5.2, and 5.3. We achieve this through our "doc:`compatibility<compatibility>` header.
* :doc:`Table<api/table>` support: setting values, getting values of multiple (different) types
- :doc:`Lazy evaluation<api/proxy>` for nested/chained queries
``table["a"]["b"]["c"] = 24;``
- Implicit conversion to the types you want
``double b = table["computed_value"];``
* Support for callables (functions, lambdas, member functions)
- Pull out any Lua function with :doc:`sol::function<api/function>`
``sol::function fx = table["socket_send"];``
- Can also set callables into :doc:`operator[] proxies<api/proxy>`
``table["move_dude"] = engine::move_dude;``
- Safety: use :doc:`sol::protected_function<api/protected_function>` to catch any kind of error
+ ANY kind: C++ exception or Lua erors are trapped and run through the optional ``error_handler`` variable
- *Advanced:* Overloading of a single function so you don't need to do boring typechecks
* User-Defined Type (:doc:`sol::usertype<api/usertype>` in the API) support:
- Set member functions to be called
- Set member variables
- Use free-functions that take the Type as a first argument (pointer or reference)
- Support for "Factory" classes that do not expose constructor or destructor
- Modifying memory of userdata in C++ directly affects Lua without copying, and
- Modifying userdata in Lua directly affects C++ references/pointers
``my_class& a = table["a"];``
``my_class* a_ptr = table["a"];``
- If you want a copy, just use value semantics and get copies:
``my_class a = table["a"];``
* Thread/Coroutine support
- Use, resume, and play with :doc:`<coroutines<api/coroutine>` like regular functions
- Get and use them even on a separate Lua :doc:`thread<api/thread>`
- Monitor status and get check errors
* *Advanced:* Customizable and extensible to your own types if you override :doc:`getter/pusher/checker<api/stack>` template struct definitions.
The Feature Matrix™
-------------------
The below feature table checks for the presence of something. It, however, does not actually account for any kind of laborious syntax.
✔ full support
- partial support / wonky support
✗ no support
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| | plain C | luawrapper | lua-intf | luabind | Selene | Sol | oolua | lua-api-pp | kaguya |
| | | | | | | | | | |
+===========================+=============+============+==========+=========+==========+===========+===========+================+==========+
| tables | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| table chaining | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| arbitrary keys | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| user-defined types (udts) | - | ✔ | ✔ | ✔ | ✔ | ✔ | - | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| udts: member functions | - | ✔ | ✔ | ✔ | ✔ | ✔ | - | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| udts: variables | - | - | - | - | - | ✔ | - | - | - |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| stack abstractions | - | ✔ | - | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| function binding | - | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| protected function | ✔ | ✗ | - | - | - | ✔ | - | ✔ | - |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| multi-return | - | ✗ | ✗ | ✔ | ✔ | ✔ | - | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| inheritance | - | ✗ | ✗ | ✔ | ✔ | ✔ | - | - | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| overloading | - | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✗ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| thread | ✔ | ✗ | ✗ | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| coroutines | ✔ | ✗ | ✗ | ✔ | ✔ | ✔ | ✗ | ✗ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| no-rtti support | ✔ | ✗ | - | ✗ | ✗ | ✔ | ✗ | ✗ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| no-exception support | ✔ | ✗ | - | - | ✗ | ✔ | ✗ | ✗ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| Lua 5.1 | ✔ | ✔ | - | ✔ | ✗ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| Lua 5.2 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| Lua 5.3 | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| luajit | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
| distribution | compile | header | both | compile | header | header | compile | compile | header |
+---------------------------+-------------+------------+----------+---------+----------+-----------+-----------+----------------+----------+
notes on implementations
------------------------
Plain C -
* Obviously you can do anything you want with Plain C, but the effort involved is astronomical in comparison to what frameworks offer
* Does not scale very well (in terms of developer ease of use)
* Compilation (or package manager use) is obviously required for your platform and required to use ANY of these libraries whatsoever
luawrapper -
* Takes the approach of writing and reading tables using ``readVariable`` and ``writeVariable`` functions
* C++11
* No macros
* The interface can be clunky (no table-like data structures: most things go though ``readVariable`` / ``writeVariable``)
lua-intf -
* Can be both header-only or compiled
* C++11
* Macro-based registration (strange pseudo-language)
* Fairly fast in most regards
* Registering classes/"modules" in using C++ code is extremely verbose
luabind -
* One of the older frameworks, but has many people updating it and providing "deboostified" versions
* Strange in-lua keywords and parsing to allow for classes to be written in lua
- not sure if good feature; vendor lock-in to that library to depend on this specific class syntax?
Selene -
* member variables are automatically turned into ``obj:set_x( value )`` to set and ``obj:x()`` to get
* Registering classes/"modules" in using C++ code is extremely verbose
Sol -
* Overloading support can get messy with inheritance, see :doc:`here<api/overload>`
* Only (?) library that supports table-like use of variables as shown in the :doc:`sneak peek<index>`
* C++14/"C++1y" (-std=c++14, -std=c++1y, =std=c++1z) flags are used (available since GCC 4.9 and Clang 3.5)
oolua -
* The syntax for this library is thicker than a brick. No, seriously. `Go read the docs.`_
.. _ fn1:
lua-api-pp -
* Compiled, but the recommendation is to add the source files directly to your project
* Userdata registration with nice, thick macros: LUAPP_USERDATA( ... ) plus a bunch of free functions that take a ``T& self`` argument
* C++11-ish in some regards
kaguya -
* Probably the closest in implementation details and interface to Sol itself
* Inspired coroutine support for Sol
* Library author (satoren) is a nice guy!
* C++11/14, or boostified (which makes it C++03 compatible)
.. _Go read the docs.: https://oolua.org/docs/index.html

103
docs/source/index.rst Normal file
View File

@ -0,0 +1,103 @@
.. Sol documentation master file, created by
sphinx-quickstart on Mon Feb 29 21:49:51 2016.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Sol 2.0.0
=========
a fast, simple C++ and Lua Binding
----------------------------------
Contents:
---------
.. toctree::
:maxdepth: 1
:name: mastertoc
:caption: Contents
features
benchmarks
exceptions
rtti
api/top
licenses
"I need feature X, maybe you have it?"
--------------------------------------
Take a look at the :doc:`Features<features>` page: it links to much of the API. Don't see a feature you want? Send inquiries for support for a particular abstraction to the `issues`_ tracker.
The Basics:
-----------
.. note::
More examples can be found in the `examples directory`_
.. code-block:: c++
:caption: functions
:linenos:
#include <sol.hpp>
#include <cassert>
int main() {
sol::state lua;
int x = 0;
lua.set_function("beep", [&x]{ ++x; });
lua.script("beep()");
assert(x == 1);
sol::function beep = lua["beep"];
beep();
assert(x == 2);
return 0;
}
.. code-block:: c++
:caption: linking C++ structures to Lua
:linenos:
#include <sol.hpp>
#include <cassert>
struct vars {
int boop = 0;
int bop () const {
return boop + 1;
}
};
int main() {
sol::state lua;
lua.new_usertype<vars>("vars",
"boop", &vars::boop
"bop", &vars::bop);
lua.script("beep = vars.new()\n"
"beep.boop = 1\n"
"bopvalue = beep.bop()");
vars& beep = lua["beep"];
int bopvalue = lua["bopvalue"];
assert(beep.boop == 1);
assert(lua.get<vars>("beep").boop == 1);
assert(beep.bop() == 2);
assert(bopvalue == 2);
return 0;
}
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
.. _issues: http://github.com/ThePhD/sol2/issues
.. _examples directory: https://github.com/ThePhD/sol2/tree/develop/examples

47
docs/source/licenses.rst Normal file
View File

@ -0,0 +1,47 @@
licenses
========
The following licenses cover all of the code in Sol. Spoiler: they're all `MIT`_ and it's safe to use in commercial code: feel free to copy/paste the below right into your own attributions / licenses file.
Sol - ThePhD/sol2:
------------------
The MIT License (MIT)
Copyright (c) 2013-2016 Rapptz, ThePhD, and contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Lua-compat-5.3 - keplerproject/Lua-compat-5.3:
----------------------------------------------
The MIT License (MIT)
Copyright (c) 2015 Kepler Project.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Lua - Lua.org:
--------------
The MIT License (MIT)
Copyright © 19942015 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
.. _MIT: http://opensource.org/licenses/MIT

10
docs/source/rtti.rst Normal file
View File

@ -0,0 +1,10 @@
run-time type information (rtti)
================================
because somebody's going to want to shut this off, too...
---------------------------------------------------------
Not compiling with C++'s run-time type information? Do a ``#define SOL_NO_RTII`` before you include ``sol.hpp`` or define ``SOL_NO_RTTI`` on your command line. Be sure to understand the :doc:`implications<api/usertype>` of doing so if you also turn off exceptions.
If you come across bugs or can't compile because there's a stray `typeid` or `typeinfo` that wasn't hidden behind a ``#ifndef SOL_NO_RTTI``, please file `an issue`_ or even make a pull request so it can be fixed for everyone.
.. _an issue: https://github.com/ThePhD/sol2/issues

View File

@ -25,6 +25,7 @@
#include <string>
#include <array>
#include <cstdlib>
#include <cctype>
#if defined(__GNUC__) || defined(__clang__)
#include <cxxabi.h>
@ -64,6 +65,12 @@ inline std::string get_type_name() {
if (start < name.size() - 1)
start += 1;
name = name.substr(start, end - start);
if (name.find("struct", 0) == 0)
name.replace(0, 6, "", 0);
if (name.find("class", 0) == 0)
name.replace(0, 5, "", 0);
while (name.size() > 0 && std::isblank(name.front())) name.erase(name.begin(), ++name.begin());
while (name.size() > 0 && std::isblank(name.back())) name.erase(--name.end(), name.end());
return name;
}

View File

@ -40,18 +40,6 @@ struct implicit_wrapper {
}
};
inline bool check_types(types<>, std::index_sequence<>, lua_State*, int) {
return true;
}
template <typename Arg, typename... Args, std::size_t I, std::size_t... In>
inline bool check_types(types<Arg, Args...>, std::index_sequence<I, In...>, lua_State* L, int start = 1) {
if (!stack::check<Arg>(L, start + I, no_panic))
return false;
return check_types(types<Args...>(), std::index_sequence<In...>(), L, start);
}
template<typename T, typename Func, typename = void>
struct functor {
typedef meta::callable_traits<Func> traits_type;

View File

@ -57,7 +57,7 @@ inline int overload_match_arity(types<Fx, Fxs...>, std::index_sequence<I, In...>
if (traits::arity != fxarity) {
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<traits::arity, M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
if (!function_detail::check_types(args_type(), args_indices(), L, start)) {
if (!stack::stack_detail::check_types<true>().check(args_type(), args_indices(), L, start, no_panic)) {
return overload_match_arity(types<Fxs...>(), std::index_sequence<In...>(), std::index_sequence<M...>(), std::forward<Match>(matchfx), L, fxarity, start, std::forward<Args>(args)...);
}
return matchfx(types<Fx>(), Index<I>(), return_types(), args_type(), L, fxarity, start, std::forward<Args>(args)...);

View File

@ -430,13 +430,13 @@ struct checker<T*, type::userdata, C> {
if (indextype == type::nil) {
return true;
}
return checker<T, type::userdata, C>{}.check(L, indextype, index, handler);
return checker<T, type::userdata, C>{}.check<T*>(L, indextype, index, handler);
}
};
template <typename T, typename C>
struct checker<T, type::userdata, C> {
template <typename Handler>
template <typename U = T, typename Handler>
static bool check (lua_State* L, type indextype, int index, const Handler& handler) {
if (indextype != type::userdata) {
handler(L, index, type::userdata, indextype);
@ -448,46 +448,46 @@ struct checker<T, type::userdata, C> {
handler(L, index, type::userdata, indextype);
return false;
}
luaL_getmetatable(L, &usertype_traits<T>::metatable[0]);
luaL_getmetatable(L, &usertype_traits<U>::metatable[0]);
const type expectedmetatabletype = get<type>(L);
if (expectedmetatabletype == type::nil) {
lua_pop(L, 2);
handler(L, index, type::userdata, indextype);
return false;
}
bool success = lua_rawequal(L, -1, -2) == 1;
#ifndef SOL_NO_EXCEPTIONS
if (!success) {
lua_getfield(L, -2, &detail::base_class_check_key[0]);
void* basecastdata = stack::get<light_userdata_value>(L);
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
success |= detail::catch_check<T>(basecast);
lua_pop(L, 1);
}
#elif !defined(SOL_NO_RTTI)
if (!success) {
lua_getfield(L, -2, &detail::base_class_check_key[0]);
if (stack::get<type>(L) != type::nil) {
void* basecastdata = stack::get<light_userdata_value>(L);
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
success |= ic(typeid(T));
if (expectedmetatabletype != type::nil) {
if (lua_rawequal(L, -1, -2) == 1) {
lua_pop(L, 2);
return true;
}
lua_pop(L, 1);
}
lua_pop(L, 1);
#ifndef SOL_NO_EXCEPTIONS
lua_getfield(L, -1, &detail::base_class_check_key[0]);
void* basecastdata = stack::get<light_userdata_value>(L);
detail::throw_cast basecast = (detail::throw_cast)basecastdata;
bool success = detail::catch_check<T>(basecast);
#elif !defined(SOL_NO_RTTI)
lua_getfield(L, -1, &detail::base_class_check_key[0]);
if (stack::get<type>(L) == type::nil) {
lua_pop(L, 2);
return false;
}
void* basecastdata = stack::get<light_userdata_value>(L);
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
bool success = ic(typeid(T));
#else
// Topkek
if (!success) {
lua_getfield(L, -2, &detail::base_class_check_key[0]);
if (stack::get<type>(L) != type::nil) {
void* basecastdata = stack::get<light_userdata_value>(L);
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
success |= ic(detail::id_for<T>::value);
}
lua_pop(L, 1);
lua_getfield(L, -1, &detail::base_class_check_key[0]);
if (stack::get<type>(L) == type::nil) {
lua_pop(L, 2);
return false;
}
void* basecastdata = stack::get<light_userdata_value>(L);
detail::inheritance_check_function ic = (detail::inheritance_check_function)basecastdata;
bool success = ic(detail::id_for<T>::value);
#endif // No Runtime Type Information || Exceptions
lua_pop(L, 2);
return success;
if (!success) {
handler(L, index, type::userdata, indextype);
return false;
}
return true;
}
template <typename Handler>
@ -819,36 +819,37 @@ inline std::pair<T, int> get_as_upvalues(lua_State* L, int index = 1) {
}
template <bool b>
struct check_arguments {
template <std::size_t I0, std::size_t... I, typename Arg0, typename... Args>
static bool check(types<Arg0, Args...>, std::index_sequence<I0, I...>, lua_State* L, int firstargument) {
if (!stack::check<Arg0>(L, firstargument + I0))
struct check_types {
template <std::size_t I0, std::size_t... I, typename Arg0, typename... Args, typename Handler>
static bool check(types<Arg0, Args...>, std::index_sequence<I0, I...>, lua_State* L, int firstargument, Handler&& handler) {
if (!stack::check<Arg0>(L, firstargument + I0, handler))
return false;
return check(types<Args...>(), std::index_sequence<I...>(), L, firstargument);
return check(types<Args...>(), std::index_sequence<I...>(), L, firstargument, std::forward<Handler>(handler));
}
static bool check(types<>, std::index_sequence<>, lua_State*, int) {
template <typename Handler>
static bool check(types<>, std::index_sequence<>, lua_State*, int, Handler&&) {
return true;
}
};
template <>
struct check_arguments<false> {
template <std::size_t... I, typename... Args>
static bool check(types<Args...>, std::index_sequence<I...>, lua_State*, int) {
struct check_types<false> {
template <std::size_t... I, typename... Args, typename Handler>
static bool check(types<Args...>, std::index_sequence<I...>, lua_State*, int, Handler&&) {
return true;
}
};
template <bool checkargs = default_check_arguments, std::size_t... I, typename R, typename... Args, typename Fx, typename... FxArgs, typename = std::enable_if_t<!std::is_void<R>::value>>
inline R call(types<R>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
check_arguments<checkargs>{}.check(ta, tai, L, start);
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
return fx(std::forward<FxArgs>(args)..., stack::get<Args>(L, start + I)...);
}
template <bool checkargs = default_check_arguments, std::size_t... I, typename... Args, typename Fx, typename... FxArgs>
inline void call(types<void>, types<Args...> ta, std::index_sequence<I...> tai, lua_State* L, int start, Fx&& fx, FxArgs&&... args) {
check_arguments<checkargs>{}.check(ta, tai, L, start);
check_types<checkargs>{}.check(ta, tai, L, start, type_panic);
fx(std::forward<FxArgs>(args)..., stack::get<Args>(L, start + I)...);
}
} // stack_detail

View File

@ -119,7 +119,6 @@ inline void push_metatable(lua_State* L, bool needsindexfunction, Funcs&& funcs,
static const auto& gcname = meta_function_names[static_cast<int>(meta_function::garbage_collect)];
luaL_newmetatable(L, &usertype_traits<T>::metatable[0]);
int metatableindex = lua_gettop(L);
#if !defined(SOL_NO_EXCEPTIONS) || !defined(SOL_NO_RTTI)
if (baseclasscheck != nullptr) {
stack::push(L, light_userdata_value(baseclasscheck));
lua_setfield(L, metatableindex, &detail::base_class_check_key[0]);
@ -128,7 +127,6 @@ inline void push_metatable(lua_State* L, bool needsindexfunction, Funcs&& funcs,
stack::push(L, light_userdata_value(baseclasscast));
lua_setfield(L, metatableindex, &detail::base_class_cast_key[0]);
}
#endif // No Exceptions || RTTI
if (funcs.size() < 1 && metafunctable.size() < 2) {
return;
}