ofxLua

a Lua instance addon

Copyright (c) Dan Wilcox 2011-2017

BSD Simplified License.

For information on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES, see the file, "LICENSE.txt," in this distribution.

See https://github.com/danomatika/ofxLua and the Openframeworks Forum post for documentation

If you want to use Lua + openFrameworks without building your own app, check out loaf: danomatika.com/code/loaf.

Description

ofxLua is an Open Frameworks addon for running a Lua embedded scripting interpreter within an OpenFrameworks application. Using the SWIG (Simple Wrapper and Interface Generator) tool, C++ functions and classes can be bound to the Lua api allowing them to be called within a Lua script. This is useful in separating the upper level logic from the lower level application and is utilized in numerous video games and applications.

In addition, ofxLua provides bindings for the OpenFrameworks API.

Lua combines simple procedural syntax with powerful data description constructs based on associative arrays and extensible semantics. Lua is dynamically typed, runs by interpreting bytecode for a register-based virtual machine, and has automatic memory management with incremental garbage collection, making it ideal for configuration, scripting, and rapid prototyping.

SWIG is a software development tool that connects programs written in C and C++ with a variety of high-level programming languages. It is used to generate the C++ bindings which wrap the OpenFrameworks API for Lua.

(Optional) LuaJIT is a Just-In-Time Compiler (JIT) for the Lua programming language. It implements the Lua API but is optimized for performance over the standard Lua distribution. It is recommended to use LuaJIT when speed is a concern and it is enabled on embedded Linux in addon_config.mk for this reason.

OpenFrameworks is a cross platform open source toolkit for creative coding in C++

Why not Javascript?

Those coming from a Javascript background may ask "Why Lua? Why not Javascript? I like Javascript!"

Lua has a long history of use as a embedded scripting language and, as such, is both smaller & much easier to embed on pretty much every platform. The compiled language adds less than 500kb to your app binary versus many Mbs for Javascript or Python. Speed-wise, the base Lua interpreter is oftentimes faster than either language due to it's simplicity and using LuaJIT may add a speed increase of many orders of magnitude. As an embedded language, Lua makes it relatively easy to bind C/C++ functions & objects to it's scripting environment.

For these reasons, Lua has been used for game development for many years:

Those coming from an embedded computing or game development background are probably familiar with Lua while those coming from a design and/or web development are used to Javascript. In many ways, both languages share a number of similarities and the rest is due to simple syntax or design differences. When it comes down to it, no one language or environment is better than another, they just have different focuses and design backgrounds. Do not dismiss Lua because you are unfamiliar with it as not every nail needs the same hammer.

Lua is not scary, trust me :)

See:

Build Requirements

To use ofxLua, first you need to download and install OpenFrameworks. The examples are developed against the latest release version of OpenFrameworks on http://openframeworks.cc/download.

OF github repository

Currently, ofxLua is being developed on Mac OSX and has been tested on OSX, iOS, & Linux. Windows and Android should work but have not been tested.

Installation and Build

Place ofxLua within a folder in the apps folder of the OF dir tree:

openframeworks/addons/ofxLua

The easiest way to do this is via cloning with git:

cd openframeworks/addons/
git clone git://github.com/danomatika/ofxLua.git

You'll need to checkout the swig-openframeworks submodule as well using:

git submodule init
git submodule update

Which version to use?

The master branch of ofxLua will work with the current stable version of OpenFrameworks and can be considered relatively stable.

Previous versions are tagged using Semantic Versioning with the updates to newer versions of OpenFrameworks and Lua noted in the changelog, CHANGES.txt. You can select the tag in the Github "Current Branch" menu or clone and check it out using git.

If you want to use ofxLua with a previous version of OpenFrameworks, checkout the corresponding version tag after cloning:

git clone git://github.com/danomatika/ofxLua.git
cd ofxLua
git checkout 1.1.0

Dependencies

For embedded Linux (arm, Raspberry Pi, etc), LuaJIT is used for better performance. Make sure you have the luajit-5.1 development package installed.

Running the Example Projects

The example projects are in the luaExample & luaExampleIOS folders.

Project files for the examples are not included so you will need to generate the project files for your operating system and development environment using the OF ProjectGenerator which is included with the OpenFrameworks distribution.

To (re)generate project files for an existing project:

  • click the "Import" button in the ProjectGenerator
  • navigate the to base folder for the project ie. "luaExample"
  • click the "Update" button

If everything went Ok, you should now be able to open the generated project and build/run the example.

OSX

Open the Xcode project, select the "luaExample Debug" scheme, and hit "Run".

Linux

Open the Code::Blocks .cbp and hit F9 to build. Optionally, you can build the example with the Makefile.

To build and run it on the terminal:

make
make run

How to Create a New ofxLua Project

ProjectGenerator

Simply select ofxLua from the available addons in the ProjectGenerator before generating a new project.

Manual Method

To develop your own project based on ofxLua, simply copy an example project and rename it. You probably want to put it in your apps folder, for example, after copying:

openFrameworks/addons/ofxLua/example/ => openFrameworks/apps/myApps/example/

It must be 3 levels down in the openframeworks folder structure.

Then after renaming:

openFrameworks/apps/myApps/myLuaProject/

On Mac, rename the project in Xcode (do not rename the .xcodeproj file in Finder!): Long click on the project name in the project tree.

Adding ofxLua to an Existing Project

ProjectGenerator

Select ofxLua and other addons used by your project from the available addons in the ProjectGenerator, select the parent folder of your project, and set the exact name of the existing project in the text box. This will overwrite the existing project files with new ones that now include ofxLua.

Note: you will lose any custom settings you've added manually to your project.

Manual Method

If you want to add ofxLua to another project, you need to make sure you add the following src files:

openFrameworks/addons/ofxLua/src/ofxLua.h
openFrameworks/addons/ofxLua/src/ofxLua.cpp
openFrameworks/addons/ofxLua/src/ofxLuaFileWriter.h
openFrameworks/addons/ofxLua/src/ofxLuaFileWriter.cpp

and optionally

openFrameworks/addons/ofxLua/src/bindings/ofxLuaBindings.h
openFrameworks/addons/ofxLua/src/bindings/YOURPLATFORM/ofxLuaBindings.cpp

You also need to add the Lua library files in the libs directory:

openFrameworks/addons/ofxLua/libs/lua

For Xcode:

  • right click and create a new group "ofxLua"
  • drag ofxLua/src into "ofxLua"
  • drag ofxLua/libs into "ofxLua"
  • remove bindings files that do not match your platform aka remove src/bindings/desktop for iOS

On older Mac OSXs (pre 10.8), a header file which is included with the OS contains some macros which conflict with several lua macros. They can be renamed by setting this CFLAG:

-D__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0

OF API Bindings

SWIG generated bindings for the OF API can be found in src/bindings. Currently it covers most of the api while leaving out base classes. More specific documentation may come at a future date, but for now check the example scripts on usage.

Basic documentation:

There is a main "of" module and functions, classes, constants, & enums are renamed:

  • function: ofBackground -> of.background
  • class: ofColor -> of.Color
  • constant: OF_LOG_VERBOSE -> of.LOG_VERBOSE
  • enum: ofShader::POSITION_ATTRIBUTE -> of.Shader.POSITION_ATTRIBUTE
  • begin & end: these are lua keywords, so functions with this name are renamed in the following classes:
    • ofFbo: beginFbo() & endFbo()
    • ofCamera: beginCamera() & endCamera()
    • ofMaterial: beginMaterial() & endMaterial()
    • ofShader: beginShader() & endShader()

Base classes, deprecations, variable arguments (...), ofThread, ofPtr, ofMutex, & ofScopedLock are ignored for now.

Functions that return a std::vector return a wrapped std::vector in Lua. As with Lua tables, indexes start at 1.

Math & String

The basic string and math functions are provided by built-in Lua libraries:

Other standard Lua libraries are: table, io, and os.

Comparing Key Values

OF uses integers for the key event values so comparisons can be made using character literals in C++:

if(key == 'f') {
    ofToggleFullscreen();
}
else if(key == OF_KEY_UP) {
    ofLog() << "up pressed";
}

Lua does not have character literals so 'f' is treated as a string. In order to do the same comparison, convert 'f' to a number using the string library string.byte function:

if key == string.byte("f") then
    of.toggleFullscreen()
elseif key == of.KEY_UP then
    print("up pressed")
end

Working with Class Instances

Calling class member functions requires using a : character -> image:draw(20, 100, 100, 100)

Calling class member variables requires using a . character -> print(image.width)

Mixing up : and . is probably the most common pitfall when coming from C++ to Lua:

-- create instance of a class
image = of.Image()
    
-- this will cause an error
image.load("helloworld.jpg") -- using . to call member function

-- this will work
image:load("helloworld.jpg") -- use a : instead

-- access class instance properties with a .
print("Image size: "..image.width.."x"..image.height)

Details

To see the detailed differences with the OF C++ API run the following:

grep DIFF swig/openFrameworks.i

To see work to be done on the bindings run:

grep TODO swig/openFrameworks.i

Classes

Simple Lua class support is provided by the class() function from the Lua Users wiki:

-- class declaration
MyClass = class()

-- constructor & attributes
function MyClass:__init(x, y)
   self.x = x
   self.y = y
   self.radius = 4
end

-- class function
function MyClass:draw()
    of.drawEllipse(self.x, self.y, self.radius, self.radius)
end

-- create instance & access attribute
myclass = MyClass(10, 10)
myclass.x = 100

-- calling a class function, note use of : for instance function instead of .
myclass:draw()

This implementation allows for inheritance and usage is as follows:

-- inherit first class and add an attribute
OtherClass = class(MyClass)
function OtherClass:__init(x, y, z)
    MyClass.__init(self, x, y) -- call super constructor
    self.z = z
end

-- create instance of derived class & access attributes
otherclass = OtherClass(10, 10, 5)
otherclass.x = 100
otherclass.z = 100

-- calling a class function, note use of : for instance function instead of .
otherclass:draw()

Making Your Own Bindings

SWIG Interface

Create a SWIG interface file (*.i) with includes headers for the functions and classes which you want to bind. You then run SWIG with this file to generate the *.cpp wrapper.

It could be as simple as the following:.

MyCode.h, your custom code:

#pragma once

#include "ofMain.h"

float myFunction(float aNumber) {
    return aNumber+1;
}

class MyCoolClass {
    public:
        
        MyCoolClass() {
            myFloat = 0;
            myInt = 0;
            aString = "hello world";
        }
        MyCoolClass(float aNumber) {
            myFloat = aNumber;
            myInt = (int) aNumber;
            aString = "foo bar";
        }
        
        // member function
        void doSomething() {
            ofLog() << "did something: " << aString;
        }
        
        // getter/setter
        void setInt(int newInt) {myInt = newInt;}
        int getInt() {return myInt;}
        
        // member variable, read/write
        string aString;

    protected:

        // some protected member variables, won't be wrapped
        float myFloat;
        int myInt;
};

MyBindings.i, your custom SWIG interface file:

%module my
%{
    // include any needed headers here
    #include "MyCode.h"
%}

// include support for some common C++ STL types you might be using,
// see http://swig.org/Doc3.0/Library.html#Library_stl_cpp_library
%include <stl.i>
%include <std_string.i>
%include <std_vector.i>
%include <std_map.i>

// if you're using "string" instead of "std::string" (like the openFrameworks source code),
// you'll need this so swig will know that a "string" can be considered a "std::string"
typedef std::string string;

// include custom code you want to be wrapped,
// note the '%' instead of '#' as '%include' is a SWIG
// command to wrap code in the given header
%include "MyCode.h"

That's it, swig will handle the rest! Of course this is a simple example but there are lots more options for specific bindings settings such as generating properties from getters & setters, etc.

Generate .cpp Wrapper

Now call SWIG to generate your .cpp wrapper:

swig -c++ -lua -fcompact -fvirtual -I../../../libs/openFrameworks MyBindings.i

Make sure to add search paths to headers used by your code (aka the "-I" line in the command above).

If all went well, SWIG will have generated the MyBindings_wrap.cxx C++ file. Put this into your project's source directory and build it with your project.

Opening Your Lua Library

You will need to open your new Lua library provided by the SWIG-generated .cpp file in order to use it in your lua state.

SWIG creates a "luaopen" C function using your module name which, in this case, will be "luaopen_my". This function needs to be defined in C++ in order to be used, so add it to the top of the .cpp file where you initialize your ofxLua object:

// declare the module bindings
extern "C" {
    int luaopen_my(lua_State* L);
}

Then call this function after initing ofxLua:

lua.init(true);
luaopen_my(lua); // open bindings

Using Your Lua Library

If everything is working, you should be able to call your bindings in Lua using your new "my" module:

aNumber = my.myFunction(3.45)

-- class
coolClass = my.MyCoolClass() -- constructor
coolClass = my.MyCoolClass(1.23) -- constructor with float

-- note: use ':' not '.' to call class instance member functions
coolClass:doSomething()

-- call the setter function
coolClass:setInt(4)

-- properties are accessed with a '.'
coolClass.aString = "hello world"

See the SWIG interface file in swig and the SWIG and Lua documentation for more information. SWIG will handle most general cases for you, but there are plenty of details to get into if you want greater customization.

If you end up having lots of custom code to bind, it's recommended to create multiple SWIG interface files which are included into a single *.i using the %include command. Do not create separate files with the same module name, only set the module in the main file as SWIG is designed for 1 module per main interface.

Do not open issues or bug reports if the problem is in writing your own bindings as this is all handled by SWIG. Be sure to search online for similar errors with "swig" as part of your search. More likely than not, it's an issue with your bindings and not with ofxLua.

Debugging Symbols and Syntax

When writing bindings, it's often helpful to see what C++ symbols (classes, functions, etc) are being bound to Lua by SWIG. You have SWIG generate a list of language symbols it sees while processing using the -debug-lsymbols option. It's often helpful to pipe this into a file:

swig -c++ -lua -fcompact -fvirtual -I../../../libs/openFrameworks -debug-lsymbols MyBindings.i > my_symbols.txt

This file can also be used as the basis for generating a list of keywords for autocompletion. For instance, the scripts/lua_syntax.py script parses the SWIG symbol output format into a simple list of all available symbols in lua module. The following creates a text file listing the global symbols as well as per class symbols found in the "my" module from the my_symbol.txt file generated by SWIG:

ofxLua/scripts/lua_syntax.py my my_symbols.txt

This generates a my_syntax.txt which is easier to use than the base SWIG output.

Lua require

Lua's require command will import scripts but doesn't know about the OF data path, so it will fail when using a relative path since the working directory for an OF app is the executable directory by default:

YourApp/bin/data/scriptA.lua
YourApp/bin/data/scriptB.lua

scriptA.lua:

require "scriptB"

require will fail since the current working directory is not YourApp/bin/data.

The easiest fix for this is to change the current working directory of the app to the directory of the script which is calling require. Setting the changeDir argument to true when calling ofxLua::doScript() will change the directory for you:

lua.doScript("scriptA.lua"); // doesn't change path, require will fail

lua.doScript("scriptA.lua", true); // changes path to script's parent dir, require should work

This will not effect the OF data path.

Developing

You can help develop ofxLua on GitHub: https://github.com/danomatika/ofxLua

Create an account, clone or fork the repo, then request a push/merge.

If you find any bugs or suggestions please log them to GitHub as well.

Known Issues

ld: -pie error on iOS

If you get the following error after generating an iOS app:

ld: -pie can only be used when targeting iOS 4.2 or later

change the deployment target in your project settings under the General Tab to something higher than 4.2, say 7.0.



ofxLua

一个Lua实例插件

版权所有(c) Dan Wilcox 2011-2017

BSD简化许可证。

有关使用和再分配的信息,以及免责声明 WARRANTIES,请参阅此分发中的文件LICENSE.txt。

请参阅 https://github.com/danomatika/ofxLua论坛帖子的文档

如果您想在不建立自己的应用程序的情况下使用Lua + openFramework,请查看面包 danomatika .com / code / loaf

说明

ofxLua是一个Open Frameworks插件,用于在OpenFrameworks应用程序中运行Lua嵌入式脚本解释器。使用SWIG(简单包装器和接口生成器)工具,C ++函数和类可以绑定到Lua api,允许在Lua脚本中调用它们。这在将较高级别的逻辑与较低级别的应用程序分开时有用,并且可用于许多视频游戏和应用程序

此外,ofxLua还提供了OpenFrameworks API的绑定。

Lua 将简单的过程语法与基于关联数组和可扩展语义的强大的数据描述结构相结合。 Lua是动态类型的,通过解释基于注册的虚拟机的字节码运行,并具有自动内存管理,增量垃圾收集,使其成为配置,脚本和快速原型设计的理想选择。

SWIG 是一种将C和C ++编写的程序与各种高级编程语言相连接的软件开发工具。它用于生成包含Lua的OpenFrameworks API的C ++绑定。

(可选) LuaJIT 是Lua编程语言的即时编译器(JIT)。它实现了Lua API,但是针对标准Lua分发的性能进行了优化。推荐在速度受到关注时使用LuaJIT,因为这个原因,在嵌入式Linux中启用了 addonconfig.mk

OpenFrameworks 是一种用于C ++中创意编码的跨平台开源工具包

为什么不Javascript ?

来自Javascript背景的人可能会问为什么是Lua?为什么不是JavaScript?我喜欢Javascript!

Lua作为一种嵌入式脚本语言具有悠久的使用历史,因此,它们的体积更小,更容易嵌入几乎每个平台。编译语言为您的应用程序二进制添加少于500kb,而不是许多Mbs for JavaScript或Python。速度方面,由于LuaJIT的简单性,LuaJIT的基础Lua解释器通常比任一种语言都快,因此可能会增加许多数量级的速度。作为嵌入式语言,Lua使C / C ++函数和对象到它的脚本环境。

由于这些原因,Lua已经用于游戏开发多年:

来自嵌入式计算机或游戏开发背景的用户可能熟悉Lua,而来自设计和/或Web开发的用户可以使用Javascript。在许多方面,两种语言都具有许多相似之处,而其余的则由于简单的语法或设计差异。当它归结于它时,没有一种语言或环境比另一种语言或环境更好,他们只是有不同的焦点和设计背景。不要因为你不熟悉,因为不是每个指甲都需要相同的锤子,所以不要解雇Lua。

Lua不可怕,相信我:)

请参阅:

构建要求

要使用xLua,首先需要下载并安装OpenFrameworks。这些示例是针对 http://openframeworks.cc/download 上的OpenFrameworks的最新版本开发的。

OFGithub存储库

目前,ofxLua正在Mac OSX上开发,并已在OSX,iOS和Linux。 Windows和Android应该工作,但尚未测试。

安装和构建

将OFLLL放在OF目录树的apps文件夹的文件夹中:

openframeworks/addons/ofxLua

最简单的方式是使用git克隆:

cd openframeworks/addons/
git clone git://github.com/danomatika/ofxLua.git

您还需要使用以下方式检出swig-openframeworks子模块:

git submodule init
git submodule update

要使用哪个版本?

ofxLua的主分支将使用当前稳定版本的OpenFrameworks,并且可以相对相对稳定。

以前的版本使用语义版本控制进行标记,更新版本的OpenFrameworks和Lua在更改日志CHANGES.txt中指出。您可以在Github当前分支菜单中选择该标签,或者使用git进行克隆并检查。

如果要使用以前版本的OpenFrameworksxLua,请在克隆后检出相应的版本标签:

git clone git://github.com/danomatika/ofxLua.git
cd ofxLua
git checkout 1.1.0

依赖关系

对于嵌入式Linux(arm,Raspberry Pi等), LuaJIT 用于提高性能。确保您已安装 luajit-5.1 开发包。

运行示例项目

示例项目位于 luaExample &amp; luaExampleIOS 文件夹。

不包括示例的项目文件,因此您将需要使用OpenFrameworks发行版中附带的OF ProjectGenerator为您的操作系统和开发环境生成项目文件。

要(重新)生成现有项目的项目文件
  • 点击ProjectGenerator中的导入按钮
  • 导航到项目的基本文件夹ie。 luaExample
  • 点击更新按钮

如果一切顺利,您现在应该可以打开生成的项目并构建/运行示例。

OSX

打开Xcode项目,选择luaExample Debug方案,然后点击运行。

Linux

打开Code :: Blocks .cbp并点击F9进行构建。或者,您可以使用Makefile构建示例。

要在终端上构建并运行它:

make
make run

如何创建一个新的xLua项目

ProjectGenerator

在生成新项目之前,只需从ProjectGenerator中的可用插件中选择xLua。

手册方法

要开发基于ofxLua的自己的项目,只需复制示例项目并重命名。你可能想把它放在你的应用程序文件夹中,例如:复制后:

openFrameworks/addons/ofxLua/example/ => openFrameworks/apps/myApps/example/

在openframeworks文件夹结构中必须有3个级别。

然后重命名:

openFrameworks/apps/myApps/myLuaProject/
在Mac上,在Xcode中重命名该项目(不要在Finder中重命名.xcodeproj文件):在项目树中点击项目名称。

将xLua添加到现有项目

ProjectGenerator

从ProjectGenerator中的可用插件中选择您的项目使用的xLua和其他插件,选择项目的父文件夹,并在文本框中设置现有项目的确切名称。这将覆盖现有的包含xLua的新项目文件。

注意:您将丢失手动添加到项目中的任何自定义设置。

手动方法< / h3>

如果要将xLua添加到另一个项目,则需要确保添加以下src文件:

openFrameworks/addons/ofxLua/src/ofxLua.h
openFrameworks/addons/ofxLua/src/ofxLua.cpp
openFrameworks/addons/ofxLua/src/ofxLuaFileWriter.h
openFrameworks/addons/ofxLua/src/ofxLuaFileWriter.cpp

和可选的

openFrameworks/addons/ofxLua/src/bindings/ofxLuaBindings.h
openFrameworks/addons/ofxLua/src/bindings/YOURPLATFORM/ofxLuaBindings.cpp

您还需要在libs目录中添加Lua库文件:

openFrameworks/addons/ofxLua/libs/lua

For Xcode:

  • 右键单击并创建一个新组ofxLua
  • 将xLua / src拖入ofxLua
  • 将xLua / libs拖入ofxLua
  • 删除与您的平台不匹配的绑定文件aka删除iOS的 src / bindings / desktop
在旧的Mac OSX上(10.8以前),操作系统随附的头文件包含一些与几个lua宏相冲突的宏。可以通过设置此CFLAG来重命名它们:

-D__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES=0

的API绑定

可以在 src / bindings 中找到OF API的SWIG生成的绑定。目前,它覆盖了api的大部分,同时省略了基础类。更具体的文档可能会在将来的日期出现,但现在请查看使用示例脚本。

基本文件:

有一个主要的模块和函数,类,常量和枚举名称重命名为:

  • 功能:ofBackground - &gt; of.background
  • class :ofColor - &gt; of.Color
  • 常量:OF_LOG_VERBOSE - &gt;的.LOG_VERBOSE
  • 枚举:ofShader :: POSITION_ATTRIBUTE - &gt; of.Shader.POSITION_ATTRIBUTE
  • begin &amp; end :这些是lua关键字,因此具有此名称的函数将在以下类中重命名:
    • :beginFbo()&amp; endFbo()
    • 摄像头的
    • :beginCamera()&amp; endCamera()
    • :beginMaterial()&amp; endMaterial()
    • ofShader :beginShader()&amp; endShader()

基本类,弃用,变量参数(…),ofThread,ofPtr,ofMutex,&amp; ofScopedLock现在将被忽略。

返回std :: vector的函数返回Lua中的一个包装的s​​td :: vector。与Lua表一样,索引从1开始。

Math & String

基本的字符串和数学函数由内置的Lua库提供:

其他标准的Lua库是: io os

Comparing Key Values

OF对于键事件值使用整数,因此可以使用C ++中的字符文字进行比较:

if(key == 'f') {
    ofToggleFullscreen();
}
else if(key == OF_KEY_UP) {
    ofLog() << "up pressed";
}

Lua没有字符文字,所以’f’被视为一个字符串。为了做同样的比较,使用字符串库string.byte函数将’f’转换成一个数字:

if key == string.byte("f") then
    of.toggleFullscreen()
elseif key == of.KEY_UP then
    print("up pressed")
end

Working with Class Instances

调用类成员函数需要使用:character - &gt; image:draw(20,100,100,100)

调用类成员变量需要使用a。字符 - &gt; print(image.width)

混合:和。可能是从C ++到Lua最常见的陷阱:

– create instance of a class
image = of.Image()

– this will cause an error image.load("helloworld.jpg") – using . to call member function

– this will work image:load("helloworld.jpg") – use a : instead

– access class instance properties with a . print("Image size: "..image.width.."x"..image.height)

Details

要查看与OF C ++ API的详细差异,请运行以下命令:

grep DIFF swig/openFrameworks.i

要查看执行绑定的工作,请执行以下操作:

grep TODO swig/openFrameworks.i

课程

简单的Lua类支持由 Lua用户wiki 中的class()函数提供:

– class declaration
MyClass = class()

– constructor & attributes function MyClass:__init(x, y) self.x = x self.y = y self.radius = 4 end

– class function function MyClass:draw() of.drawEllipse(self.x, self.y, self.radius, self.radius) end

– create instance & access attribute myclass = MyClass(10, 10) myclass.x = 100

– calling a class function, note use of : for instance function instead of . myclass:draw()

此实现允许继承和使用如下:

– inherit first class and add an attribute
OtherClass = class(MyClass)
function OtherClass:init(x, y, z)
    MyClass.init(self, x, y) – call super constructor
    self.z = z
end

– create instance of derived class & access attributes otherclass = OtherClass(10, 10, 5) otherclass.x = 100 otherclass.z = 100

– calling a class function, note use of : for instance function instead of . otherclass:draw()

SWIG界面

创建一个包含要绑定的函数和类的包含头文件的SWIG接口文件(* .i)。然后,使用此文件运行SWIG以生成* .cpp包装器。

可以这样简单:

MyCode.h ,您的自定义代码:

#pragma once

#include "ofMain.h"

float myFunction(float aNumber) { return aNumber+1; }

class MyCoolClass { public:

    MyCoolClass() {
        myFloat = 0;
        myInt = 0;
        aString = &#34;hello world&#34;;
    }
    MyCoolClass(float aNumber) {
        myFloat = aNumber;
        myInt = (int) aNumber;
        aString = &#34;foo bar&#34;;
    }

    // member function
    void doSomething() {
        ofLog() &lt;&lt; &#34;did something: &#34; &lt;&lt; aString;
    }

    // getter/setter
    void setInt(int newInt) {myInt = newInt;}
    int getInt() {return myInt;}

    // member variable, read/write
    string aString;

protected:

    // some protected member variables, won&#39;t be wrapped
    float myFloat;
    int myInt;

};

MyBindings.i ,您的自定义SWIG界面文件:

%module my
%{
    // include any needed headers here
    #include "MyCode.h"
%}

// include support for some common C++ STL types you might be using, // see http://swig.org/Doc3.0/Library.html#Library_stl_cpp_library %include <stl.i> %include <std_string.i> %include <std_vector.i> %include <std_map.i>

// if you're using "string" instead of "std::string" (like the openFrameworks source code), // you'll need this so swig will know that a "string" can be considered a "std::string" typedef std::string string;

// include custom code you want to be wrapped, // note the '%' instead of '#' as '%include' is a SWIG // command to wrap code in the given header %include "MyCode.h"

就这样,swig将处理其余的事情!当然,这是一个简单的例子,但是还有更多的选项用于特定的绑定设置,例如从getter&amp;设置者等。

生成.cpp Wrapper

现在调用SWIG生成.cpp包装器:

swig -c++ -lua -fcompact -fvirtual -I../../../libs/openFrameworks MyBindings.i
确保为您的代码使用的标题添加搜索路径(也称为上面命令中的-I行)。

如果一切顺利,SWIG将生成 MyBindings_wrap.cxx C ++文件。将其放入项目的源目录中,并与您的项目一起构建。

打开Lua Library

您将需要打开由SWIG生成的.cpp文件提供的新Lua库,以便在您的lua状态下使用它。

SWIG使用您的模块名称创建一个luaopenC函数,在这种情况下,它将是luaopen_my。该函数需要在C ++中进行定义才能使用,因此将其添加到.xpp对象的初始化对象的顶部。

// declare the module bindings
extern "C" {
    int luaopen_my(lua_State* L);
}

然后在启动xLua后调用此函数:

lua.init(true);
luaopen_my(lua); // open bindings

使用Lua Library

如果一切正常,您应该可以使用新的我的模块在Lua中调用绑定:

aNumber = my.myFunction(3.45)

– class coolClass = my.MyCoolClass() – constructor coolClass = my.MyCoolClass(1.23) – constructor with float

– note: use ':' not '.' to call class instance member functions coolClass:doSomething()

– call the setter function coolClass:setInt(4)

– properties are accessed with a '.' coolClass.aString = "hello world"

请参阅 swig 中的SWIG界面文件以及 SWIG和Lua 文档更多信息。 SWIG将为您处理大多数通用情况,但如果您希望进行更大的自定义,则有很多细节可供参考。

如果最终有很多自定义代码来绑定,建议使用%include命令创建多个SWIG接口文件,这些文件被包含在一个* .i文件中。不要使用相同的模块名称创建单独的文件,只能在主文件中设置模块,因为SWIG设计为每个主界面1个模块。

不要打开问题或错误报告,如果问题是编写自己的绑定,因为这一切都由SWIG处理。确保在线搜索与swig类似的错误作为搜索的一部分。更有可能的是,这是绑定的问题,而不是withxLua。

调试符号和语法

编写绑定时,通过SWIG查看什么C ++符号(类,函数等)被绑定到Lua是非常有帮助的。您使用SWIG生成一个使用 -debug-lsymbols 选项处理的语言符号列表。将其管理到文件中通常是有用的:

swig -c++ -lua -fcompact -fvirtual -I../../../libs/openFrameworks -debug-lsymbols MyBindings.i > my_symbols.txt

此文件也可用作生成自动完成的关键字列表的基础。例如, scripts / lua_syntax.py 脚本将SWIG符号输出格式解析为lua模块中所有可用符号的简单列表。以下创建一个文本文件列出全局符号以及SWIG中生成的 my_symbol.txt 文件中my模块中的每个类符号:

ofxLua/scripts/lua_syntax.py my my_symbols.txt

这会产生一个比基本SWIG输出更容易使用的 my_syntax.txt

Lua要求

Lua的 require 命令将导入脚本,但不知道OF数据路径,因此使用相对路径时将失败,因为默认情况下,OF应用程序的工作目录是可执行目录:

YourApp/bin/data/scriptA.lua
YourApp/bin/data/scriptB.lua

scriptA.lua:

require "scriptB"

require将失败,因为当前的工作目录不是 YourApp / bin / data

最简单的修复是将应用程序的当前工作目录更改为正在调用的脚本的目录。调用ofxLua :: doScript()时,将changeDir参数设置为true将更改您的目录:

lua.doScript("scriptA.lua"); // doesn't change path, require will fail

lua.doScript("scriptA.lua", true); // changes path to script's parent dir, require should work

这不会影响OF数据路径。

开发

您可以帮助在GitHub上开发xLua: https://github.com/danomatika/ofxLua

创建一个帐户,克隆或分支回购,然后请求推/合并。

如果您发现任何错误或建议,请将其记录到GitHub。

已知问题

/ svg> 在iOS上的ld:-pie错误

如果您在生成iOS应用后遇到以下错误:

ld: -pie can only be used when targeting iOS 4.2 or later

将常规选项卡下的项目设置中的部署目标更改为高于4.2的情况,例如7.0。




相关问题推荐