summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/Makefile67
-rw-r--r--examples/bindings.cpp133
-rw-r--r--examples/hello.cpp58
-rw-r--r--examples/interpreter.cpp83
-rw-r--r--examples/raii.cpp126
5 files changed, 467 insertions, 0 deletions
diff --git a/examples/Makefile b/examples/Makefile
new file mode 100644
index 000000000000..834b20fc114e
--- /dev/null
+++ b/examples/Makefile
@@ -0,0 +1,67 @@
+# Copyright 2012 Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of Google Inc. nor the names of its contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+CXX ?= c++
+CPPFLAGS ?=
+CXXFLAGS ?= -Wall -O2
+LDFLAGS ?=
+LIBS ?=
+
+LUTOK_CPPFLAGS = $$(pkg-config --cflags-only-I lutok)
+LUTOK_CXXFLAGS = $$(pkg-config --cflags-only-other lutok)
+LUTOK_LDFLAGS = $$(pkg-config --libs-only-L lutok) \
+ $$(pkg-config --libs-only-other lutok)
+LUTOK_LIBS = $$(pkg-config --libs-only-l lutok)
+
+BUILD = $(CXX) \
+ $(CPPFLAGS) $(LUTOK_CPPFLAGS) \
+ $(CXXFLAGS) $(LUTOK_CXXFLAGS) \
+ $(LDFLAGS) $(LUTOK_LDFLAGS) \
+ -o $${target} $${source} \
+ $(LIBS) $(LUTOK_LIBS)
+
+PROGRAMS = bindings hello interpreter raii
+
+.PHONY: all
+all: $(PROGRAMS)
+
+bindings: bindings.cpp
+ @target=bindings source=bindings.cpp; echo $(BUILD); $(BUILD)
+
+hello: hello.cpp
+ @target=hello source=hello.cpp; echo $(BUILD); $(BUILD)
+
+interpreter: interpreter.cpp
+ @target=interpreter source=interpreter.cpp; echo $(BUILD); $(BUILD)
+
+raii: raii.cpp
+ @target=raii source=raii.cpp; echo $(BUILD); $(BUILD)
+
+.PHONY: clean
+clean:
+ rm -f $(PROGRAMS)
diff --git a/examples/bindings.cpp b/examples/bindings.cpp
new file mode 100644
index 000000000000..dca235a8962d
--- /dev/null
+++ b/examples/bindings.cpp
@@ -0,0 +1,133 @@
+// Copyright 2012 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/// \file examples/bindings.cpp
+/// Showcases how to define Lua functions from C++ code.
+///
+/// A major selling point of Lua is that it is very easy too hook native C and
+/// C++ functions into the runtime environment so that Lua can call them. The
+/// purpose of this example program is to show how this is done by using Lutok.
+
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <map>
+#include <sstream>
+#include <stdexcept>
+#include <string>
+
+#include <lutok/exceptions.hpp>
+#include <lutok/operations.hpp>
+#include <lutok/state.ipp>
+
+
+/// Calculates the factorial of a given number.
+///
+/// \param i The postivie number to calculate the factorial of.
+///
+/// \return The factorial of i.
+static int
+factorial(const int i)
+{
+ assert(i >= 0);
+
+ if (i == 0)
+ return 1;
+ else
+ return i * factorial(i - 1);
+}
+
+
+/// A custom factorial function for Lua.
+///
+/// \pre stack(-1) contains the number to calculate the factorial of.
+/// \post stack(-1) contains the result of the operation.
+///
+/// \param state The Lua state from which to get the function arguments and into
+/// which to push the results.
+///
+/// \return The number of results pushed onto the stack, i.e. 1.
+///
+/// \throw std::runtime_error If the input parameters are invalid. Note that
+/// Lutok will convert this exception to lutok::error.
+static int
+lua_factorial(lutok::state& state)
+{
+ if (!state.is_number(-1))
+ throw std::runtime_error("Argument to factorial must be an integer");
+ const int i = state.to_integer(-1);
+ if (i < 0)
+ throw std::runtime_error("Argument to factorial must be positive");
+ state.push_integer(factorial(i));
+ return 1;
+}
+
+
+/// Program's entry point.
+///
+/// \param argc Length of argv. Must be 2.
+/// \param argv Command-line arguments to the program. The first argument to
+/// the tool has to be a number.
+///
+/// \return A system exit code.
+int
+main(int argc, char** argv)
+{
+ if (argc != 2) {
+ std::cerr << "Usage: bindings <number>\n";
+ return EXIT_FAILURE;
+ }
+
+ // Create a new Lua session and load the print() function.
+ lutok::state state;
+ state.open_base();
+
+ // Construct a 'module' that contains an entry point to our native factorial
+ // function. A module is just a Lua table that contains a mapping of names
+ // to functions. Instead of creating a module by using our create_module()
+ // helper function, we could have used push_cxx_function on the state to
+ // define the function ourselves.
+ std::map< std::string, lutok::cxx_function > module;
+ module["factorial"] = lua_factorial;
+ lutok::create_module(state, "native", module);
+
+ // Use a little Lua script to call our native factorial function providing
+ // it the first argument passed to the program. Note that this will error
+ // out in a controlled manner if the passed argument is not an integer. The
+ // important thing to notice is that the exception comes from our own C++
+ // binding and that it has been converted to a lutok::error.
+ std::ostringstream script;
+ script << "print(native.factorial(" << argv[1] << "))";
+ try {
+ lutok::do_string(state, script.str(), 0, 0, 0);
+ return EXIT_SUCCESS;
+ } catch (const lutok::error& e) {
+ std::cerr << "ERROR: " << e.what() << '\n';
+ return EXIT_FAILURE;
+ }
+}
diff --git a/examples/hello.cpp b/examples/hello.cpp
new file mode 100644
index 000000000000..40afdd5724b7
--- /dev/null
+++ b/examples/hello.cpp
@@ -0,0 +1,58 @@
+// Copyright 2012 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/// \file examples/hello.cpp
+/// Minimal example using Lua code to print a traditional hello-world message.
+
+#include <cstdlib>
+
+#include <lutok/state.ipp>
+
+
+/// Program's entry point.
+///
+/// \return A system exit code.
+int
+main(void)
+{
+ // Initializes a new Lua state. Every Lua state is independent from each
+ // other.
+ lutok::state state;
+
+ // Loads the standard library into the Lua state. Among many other
+ // functions, this gives us access to print(), which is used below.
+ state.open_base();
+
+ // Pushes the print() function into the Lua stack, then its only argument,
+ // and then proceeds to execute it within the Lua state.
+ state.get_global("print");
+ state.push_string("Hello, world!");
+ state.pcall(1, 0, 0);
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/interpreter.cpp b/examples/interpreter.cpp
new file mode 100644
index 000000000000..08fba796a45d
--- /dev/null
+++ b/examples/interpreter.cpp
@@ -0,0 +1,83 @@
+// Copyright 2012 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/// \file examples/interpreter.cpp
+/// Implementation of a basic command-line Lua interpreter.
+
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+#include <lutok/exceptions.hpp>
+#include <lutok/operations.hpp>
+#include <lutok/state.ipp>
+
+
+/// Executes a Lua statement provided by the user with error checking.
+///
+/// \param state The Lua state in which to process the statement.
+/// \param line The textual statement provided by the user.
+static void
+run_statement(lutok::state& state, const std::string& line)
+{
+ try {
+ // This utility function allows us to feed a given piece of Lua code to
+ // the interpreter and process it. The piece of code can include
+ // multiple statements separated by a semicolon or by a newline
+ // character.
+ lutok::do_string(state, line, 0, 0, 0);
+ } catch (const lutok::error& error) {
+ std::cerr << "ERROR: " << error.what() << '\n';
+ }
+}
+
+
+/// Program's entry point.
+///
+/// \return A system exit code.
+int
+main(void)
+{
+ // Create a new session and load some standard libraries.
+ lutok::state state;
+ state.open_base();
+ state.open_string();
+ state.open_table();
+
+ for (;;) {
+ std::cout << "lua> ";
+ std::cout.flush();
+
+ std::string line;
+ if (!std::getline(std::cin, line).good())
+ break;
+ run_statement(state, line);
+ }
+
+ return EXIT_SUCCESS;
+}
diff --git a/examples/raii.cpp b/examples/raii.cpp
new file mode 100644
index 000000000000..eae76538e992
--- /dev/null
+++ b/examples/raii.cpp
@@ -0,0 +1,126 @@
+// Copyright 2012 Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors
+// may be used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/// \file examples/raii.cpp
+/// Demonstrates how RAII helps in keeping the Lua state consistent.
+///
+/// One of the major complains that is raised against the Lua C API is that it
+/// is very hard to ensure it remains consistent during the execution of the
+/// program. In the case of native C code, there exist many tools that help the
+/// developer catch memory leaks, access to uninitialized variables, etc.
+/// However, when using the Lua C API, none of these tools can validate that,
+/// for example, the Lua stack remains balanced across calls.
+///
+/// Enter RAII. The RAII pattern, intensively applied by Lutok, helps the
+/// developer in maintaining the Lua state consistent at all times in a
+/// transparent manner. This example program attempts to illustrate this.
+
+#include <cassert>
+#include <cstdlib>
+#include <iostream>
+#include <string>
+
+#include <lutok/operations.hpp>
+#include <lutok/stack_cleaner.hpp>
+#include <lutok/state.ipp>
+
+
+/// Prints the string-typed field of a table.
+///
+/// If the field contains a string, this function prints its value. If the
+/// field contains any other type, this prints an error message.
+///
+/// \pre The top of the Lua stack in 'state' references a table.
+///
+/// \param state The Lua state.
+/// \param field The name of the string-typed field.
+static void
+print_table_field(lutok::state& state, const std::string& field)
+{
+ assert(state.is_table(-1));
+
+ // Bring in some RAII magic: the stack_cleaner object captures the current
+ // height of the Lua stack at this point. Whenever the object goes out of
+ // scope, it will pop as many entries from the stack as necessary to restore
+ // the stack to its previous level.
+ //
+ // This ensures that, no matter how we exit the function, we do not leak
+ // objects in the stack.
+ lutok::stack_cleaner cleaner(state);
+
+ // Stack contents: -1: table.
+ state.push_string(field);
+ // Stack contents: -2: table, -1: field name.
+ state.get_table(-2);
+ // Stack contents: -2: table, -1: field value.
+
+ if (!state.is_string(-1)) {
+ std::cout << "The field " << field << " does not contain a string\n";
+ // Stack contents: -2: table, -1: field value.
+ //
+ // This is different than when we started! We should pop our extra
+ // value from the stack at this point. However, it is extremely common
+ // for software to have bugs (in this case, leaks) in error paths,
+ // mostly because such code paths are rarely exercised.
+ //
+ // By using the stack_cleaner object, we can be confident that the Lua
+ // stack will be cleared for us at this point, no matter what happened
+ // earlier on the stack nor how we exit the function.
+ return;
+ }
+
+ std::cout << "String in field " << field << ": " << state.to_string(-1)
+ << '\n';
+ // A well-behaved program explicitly pops anything extra from the stack to
+ // return it to its original state. Mostly for clarity.
+ state.pop(1);
+
+ // Stack contents: -1: table. Same as when we started.
+}
+
+
+/// Program's entry point.
+///
+/// \return A system exit code.
+int
+main(void)
+{
+ lutok::state state;
+ state.open_base();
+
+ lutok::do_string(state, "example = {foo='hello', bar=123, baz='bye'}",
+ 0, 0, 0);
+
+ state.get_global("example");
+ print_table_field(state, "foo");
+ print_table_field(state, "bar");
+ print_table_field(state, "baz");
+ state.pop(1);
+
+ return EXIT_SUCCESS;
+}