search_index.json 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. {
  2. "docs": [
  3. {
  4. "location": "/",
  5. "text": "Installation\n\n\nLuwra is a header-only library, which means that nothing has to be compiled in order to use it.\nSimply clone the \nrepository\n or\n\ndownload\n it and extract it to a directory\nof your preference.\n\n\nFor your application to be able to reach the \nlib/luwra.hpp\n header file, you must add\n\n/path/to/luwra/lib\n to the list of include paths. With Clang and GCC that is done using the\n\n-I/path/to/luwra/lib\n command-line parameter.\n\n\nNow you can simply \n#include <luwra.hpp>\n in your C++ files and start using Luwra.\n\n\nIntegration\n\n\nThis library does not provide a standalone version of Lua nor does it isolate its features. This\nmeans that all functions and classes can operate on \nlua_State\n (or the alias\n\nState\n). Doing this allows you to integrate Luwra however you like.\n\n\nReference Manual\n\n\nA reference manual exists \nhere\n.",
  6. "title": "Home"
  7. },
  8. {
  9. "location": "/#installation",
  10. "text": "Luwra is a header-only library, which means that nothing has to be compiled in order to use it.\nSimply clone the repository or download it and extract it to a directory\nof your preference. For your application to be able to reach the lib/luwra.hpp header file, you must add /path/to/luwra/lib to the list of include paths. With Clang and GCC that is done using the -I/path/to/luwra/lib command-line parameter. Now you can simply #include <luwra.hpp> in your C++ files and start using Luwra.",
  11. "title": "Installation"
  12. },
  13. {
  14. "location": "/#integration",
  15. "text": "This library does not provide a standalone version of Lua nor does it isolate its features. This\nmeans that all functions and classes can operate on lua_State (or the alias State ). Doing this allows you to integrate Luwra however you like.",
  16. "title": "Integration"
  17. },
  18. {
  19. "location": "/#reference-manual",
  20. "text": "A reference manual exists here .",
  21. "title": "Reference Manual"
  22. },
  23. {
  24. "location": "/stack-interaction/",
  25. "text": "Stack interaction\n\n\nA fundamental aspect of this is the abstract template \nValue\n. Every type which can be\npushed onto or read from the stack has a specialization of it. Useful implementations are provided\nout of the box:\n\n\n\n\n\n\n\n\nC++ type\n\n\nPushable\n\n\nReadable\n\n\nLua type\n\n\n\n\n\n\n\n\n\n\nbool\n\n\nyes\n\n\nyes\n\n\nboolean\n\n\n\n\n\n\nsigned char\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nsigned short\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nsigned int\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nsigned long int\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nsigned long long int\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nunsigned char\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nunsigned short\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nunsigned int\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nunsigned long int\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nunsigned long long int\n\n\nyes\n\n\nyes\n\n\nnumber (integer since 5.3)\n\n\n\n\n\n\nfloat\n\n\nyes\n\n\nyes\n\n\nnumber\n\n\n\n\n\n\ndouble\n\n\nyes\n\n\nyes\n\n\nnumber\n\n\n\n\n\n\nlong double\n\n\nyes\n\n\nyes\n\n\nnumber\n\n\n\n\n\n\nconst char*\n\n\nyes\n\n\nyes\n\n\nstring\n\n\n\n\n\n\nstd::string\n\n\nyes\n\n\nyes\n\n\nstring\n\n\n\n\n\n\nstd::nullptr_t\n\n\nyes\n\n\nyes\n\n\nnil\n\n\n\n\n\n\nstd::tuple<T...>\n\n\nyes\n\n\nno\n\n\ndepends on the tuple contents\n\n\n\n\n\n\nstd::vector<T>\n\n\nyes\n\n\nyes\n\n\ntable\n\n\n\n\n\n\nstd::list<T>\n\n\nyes\n\n\nyes\n\n\ntable\n\n\n\n\n\n\nstd::map<K, V>\n\n\nyes\n\n\nyes\n\n\ntable\n\n\n\n\n\n\nlua_CFunction\n\n\nyes\n\n\nno\n\n\nfunction, table or userdata\n\n\n\n\n\n\nNativeFunction\n\n\nyes\n\n\nyes\n\n\nfunction\n\n\n\n\n\n\nTable\n\n\nyes\n\n\nyes\n\n\ntable\n\n\n\n\n\n\n\n\nNote:\n Some numeric types have a different size than their matching Lua type - they will be\ntruncated during push or read operations.\n\n\nExtending supported types\n\n\nIf you are missing a type that cannot be used as a \nuser type\n, you can add a\nspecialization of \nValue\n. All you need to do is modify the following snippet for your\ntype \nT\n.\n\n\nnamespace luwra {\n template <>\n struct Value<T> {\n static inline\n T read(State* state, int index) {\n return /* Return the instance of T that you have read at the given index */;\n }\n\n static inline\n size_t push(State* state, const T& value) {\n // Push the given value on top of the stack\n return /* Return how many values you have pushed onto the stack */;\n }\n };\n}\n\n\n\n\nPushing C++ values\n\n\nWhen pushing values onto the stack you can either use \nValue<T>::push\n or the more convenient\n\npush\n.\n\n\n// Push an integer\nluwra::push(lua, 1338);\n\n// Push a number\nluwra::push(lua, 13.37);\n\n// Push a boolean\nluwra::push(lua, false);\n\n// Push a string\nluwra::push(lua, \"Hello World\");\n\n// Push a table\nluwra::push(lua, luwra::MemberMap {\n {\"one\", 1},\n {1, \"one\"},\n {\"nested\", luwra::MemberMap {\n {\"more\", \"fields\"}\n }}\n});\n\n\n\n\nNote:\n \nluwra::MemberMap\n is an alias for\n\nstd:map<luwra::Pushable, luwra::Pushable>\n. Its keys and values are constructible using any\npushable type.\n\n\nThis produces the following stack layout:\n\n\n\n\n\n\n\n\nAbsolute Position\n\n\nRelative Position\n\n\nValue\n\n\n\n\n\n\n\n\n\n\n1\n\n\n-5\n\n\n1338\n\n\n\n\n\n\n2\n\n\n-4\n\n\n13.37\n\n\n\n\n\n\n3\n\n\n-3\n\n\nfalse\n\n\n\n\n\n\n4\n\n\n-2\n\n\n\"Hello World\"\n\n\n\n\n\n\n5\n\n\n-1\n\n\n{one = 1, [1] = \"one\", nested = {more = \"fields\"}}\n\n\n\n\n\n\n\n\nIt is possible to provide a template parameter to \npush\n to enforce pushing a specific\ntype. In most cases you are probably better off by letting the compiler infer the template\nparameter.\n\n\nReading Lua values\n\n\nSimple retrieval of Lua values is done using \nread<T>\n. Consider the stack layout\nfrom the previous example. This is how you would retrieve a value from the stack.\n\n\n// Retrieve the integer at position 1\nint value = luwra::read<int>(lua, 1);\n\n// Similiar with a relative index\nint value = luwra::read<int>(lua, -5);\n\n\n\n\nRead and type errors\n\n\nWhat happens when a value mismatches the expected type or cannot be converted to it? Most\n\nValue\n specializations use Lua's \nluaL_check*\n functions to retrieve the values from\nthe stack. This means that no exceptions will be thrown - instead the error handling is delegated to\nthe Lua VM. Have a look at the \nerror handling documentation\n for more\ninformation.",
  26. "title": "Stack Interaction"
  27. },
  28. {
  29. "location": "/stack-interaction/#stack-interaction",
  30. "text": "A fundamental aspect of this is the abstract template Value . Every type which can be\npushed onto or read from the stack has a specialization of it. Useful implementations are provided\nout of the box: C++ type Pushable Readable Lua type bool yes yes boolean signed char yes yes number (integer since 5.3) signed short yes yes number (integer since 5.3) signed int yes yes number (integer since 5.3) signed long int yes yes number (integer since 5.3) signed long long int yes yes number (integer since 5.3) unsigned char yes yes number (integer since 5.3) unsigned short yes yes number (integer since 5.3) unsigned int yes yes number (integer since 5.3) unsigned long int yes yes number (integer since 5.3) unsigned long long int yes yes number (integer since 5.3) float yes yes number double yes yes number long double yes yes number const char* yes yes string std::string yes yes string std::nullptr_t yes yes nil std::tuple<T...> yes no depends on the tuple contents std::vector<T> yes yes table std::list<T> yes yes table std::map<K, V> yes yes table lua_CFunction yes no function, table or userdata NativeFunction yes yes function Table yes yes table Note: Some numeric types have a different size than their matching Lua type - they will be\ntruncated during push or read operations.",
  31. "title": "Stack interaction"
  32. },
  33. {
  34. "location": "/stack-interaction/#extending-supported-types",
  35. "text": "If you are missing a type that cannot be used as a user type , you can add a\nspecialization of Value . All you need to do is modify the following snippet for your\ntype T . namespace luwra {\n template <>\n struct Value<T> {\n static inline\n T read(State* state, int index) {\n return /* Return the instance of T that you have read at the given index */;\n }\n\n static inline\n size_t push(State* state, const T& value) {\n // Push the given value on top of the stack\n return /* Return how many values you have pushed onto the stack */;\n }\n };\n}",
  36. "title": "Extending supported types"
  37. },
  38. {
  39. "location": "/stack-interaction/#pushing-c-values",
  40. "text": "When pushing values onto the stack you can either use Value<T>::push or the more convenient push . // Push an integer\nluwra::push(lua, 1338);\n\n// Push a number\nluwra::push(lua, 13.37);\n\n// Push a boolean\nluwra::push(lua, false);\n\n// Push a string\nluwra::push(lua, \"Hello World\");\n\n// Push a table\nluwra::push(lua, luwra::MemberMap {\n {\"one\", 1},\n {1, \"one\"},\n {\"nested\", luwra::MemberMap {\n {\"more\", \"fields\"}\n }}\n}); Note: luwra::MemberMap is an alias for std:map<luwra::Pushable, luwra::Pushable> . Its keys and values are constructible using any\npushable type. This produces the following stack layout: Absolute Position Relative Position Value 1 -5 1338 2 -4 13.37 3 -3 false 4 -2 \"Hello World\" 5 -1 {one = 1, [1] = \"one\", nested = {more = \"fields\"}} It is possible to provide a template parameter to push to enforce pushing a specific\ntype. In most cases you are probably better off by letting the compiler infer the template\nparameter.",
  41. "title": "Pushing C++ values"
  42. },
  43. {
  44. "location": "/stack-interaction/#reading-lua-values",
  45. "text": "Simple retrieval of Lua values is done using read<T> . Consider the stack layout\nfrom the previous example. This is how you would retrieve a value from the stack. // Retrieve the integer at position 1\nint value = luwra::read<int>(lua, 1);\n\n// Similiar with a relative index\nint value = luwra::read<int>(lua, -5);",
  46. "title": "Reading Lua values"
  47. },
  48. {
  49. "location": "/stack-interaction/#read-and-type-errors",
  50. "text": "What happens when a value mismatches the expected type or cannot be converted to it? Most Value specializations use Lua's luaL_check* functions to retrieve the values from\nthe stack. This means that no exceptions will be thrown - instead the error handling is delegated to\nthe Lua VM. Have a look at the error handling documentation for more\ninformation.",
  51. "title": "Read and type errors"
  52. },
  53. {
  54. "location": "/advanced-stack-interaction/",
  55. "text": "Advanced stack interaction\n\n\nInstead of extracting every Lua value seperately and pushing the result of your C++ function back\nonto the stack again, you can use one of the following functions to make this process easier for\nyou.\n\n\nManual stack layout\n\n\nThe function \ndirect\n lets you specify a \nstack signature\n in order to extract the\nvalues and invoke a \nCallable\n with them.\n\n\nWithout returning to Lua\n\n\nConsider the following:\n\n\nstring result = foo(luwra::read<string>(lua, n), luwra::read<int>(lua, n + 1));\n\n\n\n\nIt could be rewritting like this:\n\n\nstring result = luwra::direct<string(string, int)>(lua, n, foo);\n\n\n\n\nThis will read all the required values off the stack, invoke \nfoo\n with them and return its value to\nyou.\n\n\nReturning values to the stack\n\n\nAn alternative to \ndirect\n is \nmap\n. It does exactly the same, with the\nexception that it returns the resulting value back to the Lua stack.\n\n\nluwra::map<string(string, int)>(lua, n, foo);\n\n\n\n\nAutomatic stack layout\n\n\napply\n is similiar to \ndirect\n. It differs from \ndirect\n because it is\nable to infer the stack layout from the given \nCallable\n.\n\n\nProvided a function \nfoo\n which has been declared as used in the example above:\n\n\nstring foo(string bar, int baz);\n\n\n\n\nOne would use \nfoo\n like this:\n\n\nstring result = luwra::apply(lua, n, foo);\n\n\n\n\nIt also works with Lambdas, because they are function objects aswell.\n\n\nstring result = luwra::apply(lua, n, [](string a, int b) -> string {\n // Magic\n});",
  56. "title": "Advanced Stack Interaction"
  57. },
  58. {
  59. "location": "/advanced-stack-interaction/#advanced-stack-interaction",
  60. "text": "Instead of extracting every Lua value seperately and pushing the result of your C++ function back\nonto the stack again, you can use one of the following functions to make this process easier for\nyou.",
  61. "title": "Advanced stack interaction"
  62. },
  63. {
  64. "location": "/advanced-stack-interaction/#manual-stack-layout",
  65. "text": "The function direct lets you specify a stack signature in order to extract the\nvalues and invoke a Callable with them.",
  66. "title": "Manual stack layout"
  67. },
  68. {
  69. "location": "/advanced-stack-interaction/#without-returning-to-lua",
  70. "text": "Consider the following: string result = foo(luwra::read<string>(lua, n), luwra::read<int>(lua, n + 1)); It could be rewritting like this: string result = luwra::direct<string(string, int)>(lua, n, foo); This will read all the required values off the stack, invoke foo with them and return its value to\nyou.",
  71. "title": "Without returning to Lua"
  72. },
  73. {
  74. "location": "/advanced-stack-interaction/#returning-values-to-the-stack",
  75. "text": "An alternative to direct is map . It does exactly the same, with the\nexception that it returns the resulting value back to the Lua stack. luwra::map<string(string, int)>(lua, n, foo);",
  76. "title": "Returning values to the stack"
  77. },
  78. {
  79. "location": "/advanced-stack-interaction/#automatic-stack-layout",
  80. "text": "apply is similiar to direct . It differs from direct because it is\nable to infer the stack layout from the given Callable . Provided a function foo which has been declared as used in the example above: string foo(string bar, int baz); One would use foo like this: string result = luwra::apply(lua, n, foo); It also works with Lambdas, because they are function objects aswell. string result = luwra::apply(lua, n, [](string a, int b) -> string {\n // Magic\n});",
  81. "title": "Automatic stack layout"
  82. },
  83. {
  84. "location": "/wrapping/",
  85. "text": "Wrapping\n\n\nLuwra provides a simple way to generate Lua \nC functions\n from functions and class\nmembers like methods and accessors using the \nLUWRA_WRAP\n macro. These kind of C functions are\nuseful, because they work just like regular Lua functions within the Lua virtual machine.\nRegistering these functions is the most straightforward way of providing the functionality of your\napplication to Lua.\n\n\nFunctions\n\n\nWhen wrapping functions, one must consider that all parameter types must be read from the\nstack and the return type must be pushed onto the stack.\n\n\nExample\n\n\nLets assume you want to make the following function available in Lua.\n\n\nint my_function(const char* a, int b) {\n return /* magic */;\n}\n\n\n\n\nFirst, you must generate a Lua \nC function\n. One utilizes the \nLUWRA_WRAP\n macro for\nthis.\n\n\nlua_CFunction cfun = LUWRA_WRAP(my_function);\n\n\n\n\nNote:\n Do not provide the address of your function (e.g. \n&my_function\n) to any wrapping macro.\nThe macro will take care of this itself. You must provide only the name of the function.\n\n\nOnce you have the C function, you can register it in the global namespace.\n\n\nluwra::setGlobal(lua, \"my_function\", cfun);\n\n\n\n\nInvoking the function in Lua is fairly straightforward.\n\n\nprint(my_function(\"Hello World\", 1337))\n\n\n\n\nPerformance\n\n\nC functions\n are dynamically created at compile-time. All of the functions involved\nin wrapping are marked as \ninline\n, which means modern compilers produce wrapper functions with zero\noverhead, when optimization is turned on.\n\n\nFor the example above, the resulting code would look similiar to the following.\n\n\nstatic int cfun(lua_State* state) {\n lua_pushinteger(\n state,\n my_function(\n luaL_checkstring(state, 1),\n luaL_checkinteger(state, 1)\n )\n );\n return 1;\n}\n\n\n\n\nClass members\n\n\nAlthough a little trickier, it is also possible to turn C++ field accessors and methods into Lua\n\nC functions\n. The resulting Lua functions expect the first (or \nself\n) parameter to\nbe an instance of the type which the wrapped field or method belongs to.\n\n\nNote:\n Before you wrap fields and methods manually, you might want to take a look at the\n\nUser Types\n section.\n\n\nExample\n\n\nThis example will operate on the following structure.\n\n\nstruct Point {\n double x, y;\n\n // ...\n\n void scale(double f) {\n x *= f;\n y *= f;\n }\n};\n\n\n\n\nWrapping field accessors and methods works identical to wrapping functions.\n\n\nlua_CFunction cfun_x = LUWRA_WRAP(Point::x),\n cfun_y = LUWRA_WRAP(Point::y),\n cfun_scale = LUWRA_WRAP(Point::scale);\n\n// Register in global namespace\nluwra::setGlobal(lua, \"x\", cfun_x);\nluwra::setGlobal(lua, \"y\", cfun_y);\nluwra::setGlobal(lua, \"scale\", cfun_scale);\n\n\n\n\nUsage in Lua is analogous to function usage.\n\n\n-- Instantiate 'Point' here, have a look at the User Types section to find out how to do this\nlocal my_point = ...\n\n-- Access 'x' and 'y' field\nprint(x(my_point), y(my_point))\n\n-- Set 'x' and 'y' field\nx(my_point, 13.37)\ny(my_point, 73.31)\n\n-- Invoke 'scale' method\nscale(my_point, 2)",
  86. "title": "Wrapping"
  87. },
  88. {
  89. "location": "/wrapping/#wrapping",
  90. "text": "Luwra provides a simple way to generate Lua C functions from functions and class\nmembers like methods and accessors using the LUWRA_WRAP macro. These kind of C functions are\nuseful, because they work just like regular Lua functions within the Lua virtual machine.\nRegistering these functions is the most straightforward way of providing the functionality of your\napplication to Lua.",
  91. "title": "Wrapping"
  92. },
  93. {
  94. "location": "/wrapping/#functions",
  95. "text": "When wrapping functions, one must consider that all parameter types must be read from the\nstack and the return type must be pushed onto the stack.",
  96. "title": "Functions"
  97. },
  98. {
  99. "location": "/wrapping/#example",
  100. "text": "Lets assume you want to make the following function available in Lua. int my_function(const char* a, int b) {\n return /* magic */;\n} First, you must generate a Lua C function . One utilizes the LUWRA_WRAP macro for\nthis. lua_CFunction cfun = LUWRA_WRAP(my_function); Note: Do not provide the address of your function (e.g. &my_function ) to any wrapping macro.\nThe macro will take care of this itself. You must provide only the name of the function. Once you have the C function, you can register it in the global namespace. luwra::setGlobal(lua, \"my_function\", cfun); Invoking the function in Lua is fairly straightforward. print(my_function(\"Hello World\", 1337))",
  101. "title": "Example"
  102. },
  103. {
  104. "location": "/wrapping/#performance",
  105. "text": "C functions are dynamically created at compile-time. All of the functions involved\nin wrapping are marked as inline , which means modern compilers produce wrapper functions with zero\noverhead, when optimization is turned on. For the example above, the resulting code would look similiar to the following. static int cfun(lua_State* state) {\n lua_pushinteger(\n state,\n my_function(\n luaL_checkstring(state, 1),\n luaL_checkinteger(state, 1)\n )\n );\n return 1;\n}",
  106. "title": "Performance"
  107. },
  108. {
  109. "location": "/wrapping/#class-members",
  110. "text": "Although a little trickier, it is also possible to turn C++ field accessors and methods into Lua C functions . The resulting Lua functions expect the first (or self ) parameter to\nbe an instance of the type which the wrapped field or method belongs to. Note: Before you wrap fields and methods manually, you might want to take a look at the User Types section.",
  111. "title": "Class members"
  112. },
  113. {
  114. "location": "/wrapping/#example_1",
  115. "text": "This example will operate on the following structure. struct Point {\n double x, y;\n\n // ...\n\n void scale(double f) {\n x *= f;\n y *= f;\n }\n}; Wrapping field accessors and methods works identical to wrapping functions. lua_CFunction cfun_x = LUWRA_WRAP(Point::x),\n cfun_y = LUWRA_WRAP(Point::y),\n cfun_scale = LUWRA_WRAP(Point::scale);\n\n// Register in global namespace\nluwra::setGlobal(lua, \"x\", cfun_x);\nluwra::setGlobal(lua, \"y\", cfun_y);\nluwra::setGlobal(lua, \"scale\", cfun_scale); Usage in Lua is analogous to function usage. -- Instantiate 'Point' here, have a look at the User Types section to find out how to do this\nlocal my_point = ...\n\n-- Access 'x' and 'y' field\nprint(x(my_point), y(my_point))\n\n-- Set 'x' and 'y' field\nx(my_point, 13.37)\ny(my_point, 73.31)\n\n-- Invoke 'scale' method\nscale(my_point, 2)",
  116. "title": "Example"
  117. },
  118. {
  119. "location": "/user-types/",
  120. "text": "User Types\n\n\nA user type is a collection of class members bundled into a metatable. Before user types can be used\nin Lua, you must register such metatable in Lua's registry.\n\n\nThe following examples work on this class:\n\n\nstruct Point {\n double x, y;\n\n Point(double x, double y):\n x(x), y(y)\n {\n std::cout << \"Construct Point(\" << x << \", \" << y << \")\" << std::endl;\n }\n\n ~Point() {\n std::cout << \"Destruct Point(\" << x << \", \" << y << \")\" << std::endl;\n }\n\n void scale(double f) {\n x *= f;\n y *= f;\n }\n\n std::string __tostring() {\n return \"<Point(\" + std::to_string(x) + \", \" + std::to_string(y) + \")>\";\n }\n};\n\n\n\n\nRegister user type with constructor\n\n\nregisterUserType<S>\n allows\nyou to register a metatable and constructor in the global namespace. The template parameter to\n\nregisterUserType\n is a signature in the form of \nU(A...)\n where \nU\n is your user type and \nA...\n\nthe parameter types to the constructor which you want to register.\n\n\nBy default, the function generates a garbage-collector hook and a string representation function.\nIf you add a \n__gc\n or \n__tostring\n meta method to your type, these auto-generated functions will be\noverridden.\n\n\nSee this example:\n\n\nluwra::registerUserType<Point(double, double)>(\n lua,\n\n // Constructor name\n \"Point\",\n\n // Methods need to be declared here\n {\n LUWRA_MEMBER(Point, scale),\n LUWRA_MEMBER(Point, x),\n LUWRA_MEMBER(Point, y)\n },\n\n // Meta methods may be registered aswell\n {\n LUWRA_MEMBER(Point, __tostring)\n }\n);\n\n\n\n\nParameter 3 and 4 are instances of\n\nFieldVector\n. The \nLUWRA_MEMBER\n macro\ngenerates a \nstd::pair<Pushable, Pushable>\n expression.\n\n\nLUWRA_MEMBER(Point, scale) === {\"scale\", LUWRA_WRAP(Point::scale)}\n\n\n\n\nPushable\n has an implicit constructor, which makes it convenient to add other types of fields:\n\n\nluwra::registerUserType<Point(double, double)>(\n lua,\n\n // Constructor name\n \"Point\",\n\n // Methods need to be declared here\n {\n {\"scale\", LUWRA_WRAP(Point::scale)},\n {\"x\", LUWRA_WRAP(Point::x)},\n {\"y\", LUWRA_WRAP(Point::y)},\n {\"magic\", luwra::FieldVector {\n {\"number\", 1337},\n {\"string\", \"Hello World\"}\n }}\n },\n\n // Meta methods may be registered aswell\n {\n {\"__tostring\", LUWRA_WRAP(Point::__tostring)}\n }\n);\n\n\n\n\nRegister user type without constructor\n\n\nTo register only the metatable associated with a user type, simply omit the constructor parameters\nand name from the call to \nregisterUserType\n.\n\n\nluwra::registerUserType<Point>(\n lua,\n\n // Methods need to be declared here\n {\n {\"scale\", LUWRA_WRAP(Point::scale)},\n {\"x\", LUWRA_WRAP(Point::x)},\n {\"y\", LUWRA_WRAP(Point::y)},\n {\"magic\", luwra::FieldVector {\n {\"number\", 1337},\n {\"string\", \"Hello World\"}\n }}\n },\n\n // Meta methods may be registered aswell\n {\n {\"__tostring\", LUWRA_WRAP(Point::__tostring)}\n }\n);\n\n\n\n\nIt is still possible to provide a constructor using the \nLUWRA_WRAP_CONSTRUCTOR\n macro:\n\n\nlua_CFunction ctor = LUWRA_WRAP_CONSTRUCTOR(Point, double, double);\nluwra::setGlobal(lua, \"Point\", ctor);\n\n\n\n\nUsage in Lua\n\n\nAfter you have registered your user type using one of the given methods, you can start using it in\nLua:\n\n\n-- Instantiate 'Point'\nlocal point = Point(13, 37)\n\n-- Invoke 'scale' method\npoint:scale(1.5)\n\n-- Convert to string via '__tostring' meta method\nprint(point)\n\n-- Read properties 'x' and 'y'\nprint(point:x(), point:y())\n\n-- Set property 'x'\npoint:x(point.magic.number)\n\n\n\n\nManually constructing a user type\n\n\nProvided you already registered your user type, one can create it from the C++ side aswell.\n\nconstruct<U>\n provides this\nfunctionality. Given the user type and constructor parameters, it will construct the user type on\ntop of the stack:\n\n\nPoint& my_point = luwra::construct<Point>(lua, 13.37, 73.31);\n\n// Changes on C++ side will be visible in Lua\nmy_point.scale(2);\n\n\n\n\nRegistry names\n\n\nWhen registering the metatable for a user type, an automatically generated name will be used to\nstore it in the registry. When Luwra is used in a single executable or shared library, name\ncollisions should not happen. If your application consists of multiple seperate compiled units, it\nis highly recommended to prevent name collisions by defining the \nLUWRA_REGISTRY_PREFIX\n macro\nbefore including the Luwra headers. This macro changes the prefix for auto-generated registry names.\n\n\n#define LUWRA_REGISTRY_PREFIX \"MyProject#\"\n#include <luwra.hpp>\n\n\n\n\nAnother way to prevent collisons is to give each user type its individual registry name. This can be\ndone using the \nLUWRA_DEF_REGISTRY_NAME\n macro.\n\n\nstruct MyUserType {\n // ...\n};\n\nLUWRA_DEF_REGISTRY_NAME(MyUserType, \"MyUserType\")\n\n\n\n\nChoosing this method will not prefix the registry name with the value of \nLUWRA_REGISTRY_PREFIX\n.",
  121. "title": "User Types"
  122. },
  123. {
  124. "location": "/user-types/#user-types",
  125. "text": "A user type is a collection of class members bundled into a metatable. Before user types can be used\nin Lua, you must register such metatable in Lua's registry. The following examples work on this class: struct Point {\n double x, y;\n\n Point(double x, double y):\n x(x), y(y)\n {\n std::cout << \"Construct Point(\" << x << \", \" << y << \")\" << std::endl;\n }\n\n ~Point() {\n std::cout << \"Destruct Point(\" << x << \", \" << y << \")\" << std::endl;\n }\n\n void scale(double f) {\n x *= f;\n y *= f;\n }\n\n std::string __tostring() {\n return \"<Point(\" + std::to_string(x) + \", \" + std::to_string(y) + \")>\";\n }\n};",
  126. "title": "User Types"
  127. },
  128. {
  129. "location": "/user-types/#register-user-type-with-constructor",
  130. "text": "registerUserType<S> allows\nyou to register a metatable and constructor in the global namespace. The template parameter to registerUserType is a signature in the form of U(A...) where U is your user type and A... \nthe parameter types to the constructor which you want to register. By default, the function generates a garbage-collector hook and a string representation function.\nIf you add a __gc or __tostring meta method to your type, these auto-generated functions will be\noverridden. See this example: luwra::registerUserType<Point(double, double)>(\n lua,\n\n // Constructor name\n \"Point\",\n\n // Methods need to be declared here\n {\n LUWRA_MEMBER(Point, scale),\n LUWRA_MEMBER(Point, x),\n LUWRA_MEMBER(Point, y)\n },\n\n // Meta methods may be registered aswell\n {\n LUWRA_MEMBER(Point, __tostring)\n }\n); Parameter 3 and 4 are instances of FieldVector . The LUWRA_MEMBER macro\ngenerates a std::pair<Pushable, Pushable> expression. LUWRA_MEMBER(Point, scale) === {\"scale\", LUWRA_WRAP(Point::scale)} Pushable has an implicit constructor, which makes it convenient to add other types of fields: luwra::registerUserType<Point(double, double)>(\n lua,\n\n // Constructor name\n \"Point\",\n\n // Methods need to be declared here\n {\n {\"scale\", LUWRA_WRAP(Point::scale)},\n {\"x\", LUWRA_WRAP(Point::x)},\n {\"y\", LUWRA_WRAP(Point::y)},\n {\"magic\", luwra::FieldVector {\n {\"number\", 1337},\n {\"string\", \"Hello World\"}\n }}\n },\n\n // Meta methods may be registered aswell\n {\n {\"__tostring\", LUWRA_WRAP(Point::__tostring)}\n }\n);",
  131. "title": "Register user type with constructor"
  132. },
  133. {
  134. "location": "/user-types/#register-user-type-without-constructor",
  135. "text": "To register only the metatable associated with a user type, simply omit the constructor parameters\nand name from the call to registerUserType . luwra::registerUserType<Point>(\n lua,\n\n // Methods need to be declared here\n {\n {\"scale\", LUWRA_WRAP(Point::scale)},\n {\"x\", LUWRA_WRAP(Point::x)},\n {\"y\", LUWRA_WRAP(Point::y)},\n {\"magic\", luwra::FieldVector {\n {\"number\", 1337},\n {\"string\", \"Hello World\"}\n }}\n },\n\n // Meta methods may be registered aswell\n {\n {\"__tostring\", LUWRA_WRAP(Point::__tostring)}\n }\n); It is still possible to provide a constructor using the LUWRA_WRAP_CONSTRUCTOR macro: lua_CFunction ctor = LUWRA_WRAP_CONSTRUCTOR(Point, double, double);\nluwra::setGlobal(lua, \"Point\", ctor);",
  136. "title": "Register user type without constructor"
  137. },
  138. {
  139. "location": "/user-types/#usage-in-lua",
  140. "text": "After you have registered your user type using one of the given methods, you can start using it in\nLua: -- Instantiate 'Point'\nlocal point = Point(13, 37)\n\n-- Invoke 'scale' method\npoint:scale(1.5)\n\n-- Convert to string via '__tostring' meta method\nprint(point)\n\n-- Read properties 'x' and 'y'\nprint(point:x(), point:y())\n\n-- Set property 'x'\npoint:x(point.magic.number)",
  141. "title": "Usage in Lua"
  142. },
  143. {
  144. "location": "/user-types/#manually-constructing-a-user-type",
  145. "text": "Provided you already registered your user type, one can create it from the C++ side aswell. construct<U> provides this\nfunctionality. Given the user type and constructor parameters, it will construct the user type on\ntop of the stack: Point& my_point = luwra::construct<Point>(lua, 13.37, 73.31);\n\n// Changes on C++ side will be visible in Lua\nmy_point.scale(2);",
  146. "title": "Manually constructing a user type"
  147. },
  148. {
  149. "location": "/user-types/#registry-names",
  150. "text": "When registering the metatable for a user type, an automatically generated name will be used to\nstore it in the registry. When Luwra is used in a single executable or shared library, name\ncollisions should not happen. If your application consists of multiple seperate compiled units, it\nis highly recommended to prevent name collisions by defining the LUWRA_REGISTRY_PREFIX macro\nbefore including the Luwra headers. This macro changes the prefix for auto-generated registry names. #define LUWRA_REGISTRY_PREFIX \"MyProject#\"\n#include <luwra.hpp> Another way to prevent collisons is to give each user type its individual registry name. This can be\ndone using the LUWRA_DEF_REGISTRY_NAME macro. struct MyUserType {\n // ...\n};\n\nLUWRA_DEF_REGISTRY_NAME(MyUserType, \"MyUserType\") Choosing this method will not prefix the registry name with the value of LUWRA_REGISTRY_PREFIX .",
  151. "title": "Registry names"
  152. }
  153. ]
  154. }