레이블이 Lua인 게시물을 표시합니다. 모든 게시물 표시
레이블이 Lua인 게시물을 표시합니다. 모든 게시물 표시

2017년 1월 15일 일요일

Lua 입문 ( C언어 비교 ) (2)

지난글에 이어서 작성하였습니다.

Lua 변수 scope (변수 존재 범위)

로컬 변수는 local을 붙여줍니다. 안 붙어있으면 정의된 이후로 모두 사용이 가능합니다.
C
#include <stdio.h>

int main(void) {
 int a = 0;
 {
     a = 50;
     int a = 100;
     printf("%d\n",a);
 }
 printf("%d\n",a);
 return 0;
}
Lua
a = 0
do
    a = 50
    local a=100
    print (a)
end

print (a)
결과
100
50

Lua function

function의 시작은 function 이름 그리고 마지막에 end로 끝납니다. 만약 중간에 리턴값이 있으면 return 을 사용해도 됩니다.
예를 보시죠
C
#include <stdio.h>

int sumfunc(int param1,int param2)
{
    return (param1+param2);
}
int main(void) {
 printf("%d\n",sumfunc(1,2));
 return 0;
}
Lua
function sumfunc(param1,param2)
    return (param1+param2)
end

print (sumfunc(1,2))
결과
3

function 정의는 사용전에 앞쪽에서 이루어져야 합니다. 위의 예에서 sumfunc가 아래쪽에 위치한다면 오류가 발생합니다.
Lua의 다른 언어와 다른점은 변수를 여러개가 리턴이 가능합니다.
Lua 변수 여러개 리턴
function sumfunc(param1,param2)
    return (param1+param2),param1,param2
end

sum,p1,p2=sumfunc(1,2)
print (sum,p1,p2)
결과
3 1 2

Lua table

Lua언어에는 배열이 존재하지 않습니다. 그러면 비슷하게 처리할수 있는 뭔가가 있을겁니다. 그것이 table입니다. 일단 예제를 보시죠
C
#include <stdio.h>

int data[]={3,2,1};
int main(void) {
    int i;
 for(i=0;i<3;i++){
     printf("%d\n",data[i]);
 }
 return 0;
}
Lua
data={3,2,1}

for i=1,3,1 do
    print (data[i])
end
---------------------
data={[0]=3,2,1}

for i=0,2,1 do
    print (data[i])
end
결과
3
2
1
결과는 모두 동일 하지만 Lua는 index가 1부터 시작합니다. 그래서 index를 0부터 시작하게 하려면 [0]=3 과 같은 처리가 필요합니다.
사실 table의 진정한 의미는 map과 비슷합니다. 즉 index가 key가 되고 들어있는 값은 value라고 생각하면 됩니다.
Lua
data={["a"]=3,2,1}

print (data["a"])
결과
3
위의 예제에서 data={["a"]=3,["b"]=2,["b"]=1} 이 되지는 않습니다. data={["a"]=3,[1]=2,[2]=1} 이와 같이 됩니다.
index가 숫자가 아닌경우가 있다면 전체를 순회할만한 방법이 있어야 합니다. 모든 tree를 순회하기 방법이 ipairs랑 pairs 두가지 방법이 있습니다. ipairs를 이용하면 index가 숫자인 부분만 사용합니다.
Lua
data={["a"]=3,2,[5]=1,0}

print ("ipairs")
for i,v in ipairs(data) do 
    print (i,v)
end

print ("pairs")
for k,v in pairs(data) do 
    print (k,v)
end
결과
ipairs
1 2
2 0
pairs
1 2
2 0
a 3
5 1

Lua table or string 길이 구하기 rawlen, #

사용시 주의할점이 있습니다. table에서는 숫자 index의 연속적인 앞쪽 구간만 나오게 됩니다.
Lua
data={3,2,0}
print (rawlen(data))
print (#data)

data={["a"]=3,2,[5]=1,0}
print (rawlen(data))
print (#data)

data="stringdata"
print (rawlen(data))
print (#data)
결과
3
3
2
2
10
10


Lua print시 개행 관련

lua print는 항상 개행이 포함됩니다. 간혹 개행을 원치않을 경우가 있습니다.
이때 사용하는게 io.write 혹은 .. 을 사용하게 됩니다.
Lua
data1=2
data2=3
print(data1..data2)
io.write(data1)
io.write(data2)
io.write("\n")
print("end")
결과
23
23
end


Lua string 조작

관련해서 몇개의 함수의 예제를 만들었습니다.
string.byte: string 특정 위치의 값을 숫자 형태로 읽어옵니다.
string.char:숫자를 문자 형태로 바꿉니다.
string.find:string에서 특수한 문자를 찾을 때 사용합니다. 이때 사용하는 정규 식은 다음 링크를 참고하시기 바랍니다. http://www.lua.org/manual/5.3/manual.html#6.4.1
string.sub:string에서 일부를 떼어내어 sub string으로 만듭니다.
Lua
--string.byte
print("string.byte example")
data="101ABCDE"
data1=string.byte(data,4)
data2=string.byte(data,4,5)
data3,data4 = string.byte(data,4,5)
print(type(data1),data1)
print(type(data2),data2)
print(type(data3),data3)
print(type(data4),data4)

-----------------------------------
--string.char
print("string.char example")
data1=string.char(65,66,67)
print(type(data1),data1)

-----------------------------------
--string.find
--http://www.lua.org/manual/5.3/manual.html#6.4.1
print("string.find example")
data="101ABCDEABCDE"
a,b=string.find(data,"ABC",1)
print(type(a),a)
print(type(b),b)
a,b=string.find(data,"ABC",b)
print(type(a),a)
print(type(b),b)

-----------------------------------
--string.sub (s, i [, j])
print("string.sub example")
data="101ABCDEABCDE"
a,b=string.find(data,"ABC",1)
data1=string.sub(data,a,b)
print(type(data1),data1)
결과
string.byte example
number 65
number 65
number 65
number 66
string.char example
string ABC
string.find example
number 4
number 6
number 9
number 11
string.sub example
string ABC


Lua print시 포맷팅

string 함수를 이용하며 기본적으로는 C 언어와 비슷합니다.
Lua
data=string.format("%f %d %i %s %% %c",10.0,10,10,"Str",65)
print(data)
print(string.format("%f %d %i %s %% %c",10.0,10,10,"Str",65))
결과
10.000000 10 10 Str % A
10.000000 10 10 Str % A



Lua comment 주석

두가지가 있습니다. line comment는 -- 두개입니다. 또하나는 block comment 입니다.
--[[ 로 시작하며 ]]-- 로 끝납니다. block comment는 중첩이 가능합니다.

Lua
--comment
--[[
print(10)
--]]
print("end")
결과
end

Lua string to value, value to string

tonumber , tostring 함수를 이용합니다. tonumber 뒤쪽에 진법인자를 사용하지 않으면 10진수로 변환이 됩니다.
Lua
data="101"
print(type(data),data)
data = tonumber (data)
print(type(data),data)
data = tonumber (data,"2")
print(type(data),data)
data = tostring(data)
print(type(data),data)
결과
string 101
number 101
number 5
string 5




이전에 쓴글
Lua 입문 ( C언어 비교 ) (1)
http://swlock.blogspot.com/2017/01/lua-c-1.html



2017년 1월 12일 목요일

Lua 입문 ( C언어 비교 ) (1)


들어가기에 앞서

Lua 를 알게된지 몇년은 된것 같은데, 제대로된 정리를 아직까지 못했는것 같습니다. 필요할때마다 구글링해가면서 쓰고는 또 까먹고 또 검색해 보고 구현하다 보면 실수하고 암튼 계속 검색을 하게 됩니다.
쉬운(?) C언어와 비교 예제를 제작해 알기쉽게 정리 하도록 하겠습니다.


Lua

Lua는 혼자 독립적으로 사용하는 언어라기보다는 다른 언어와 같이 사용하기 위한 언어입니다. 어떤 프로젝트에서 스크립트언어가 필요하다면 Lua스크립트를 사용할것을 추천합니다. C언어 연결도 굉장히 쉽게 되어있으며 LuaJ project도 진행되어 사용하기가 쉽습니다.
키워드도 몇개 되지 않지만 기존 언어들과 조금 차이가 있는 부분들이 있어서 사용시 주의가 필요한 부분도 있습니다.

내장 키워드
     and       break     do        else      elseif
     end       false     for       function  if
     in        local     nil       not       or
     repeat    return    then      true      until     while
연산자 및 토큰
     +     -     *     /     %     ^     #
     ==    ~=    <=    >=    <     >     =
     (     )     {     }     [     ]
     ;     :     ,     .     ..    ...

Lua 변수형 타입

Lua에서는 변수형 타입이 없습니다. 따라서 a=100 과 같이 값을 입력해주면 됩니다.
int a=100; (이런식으로 사용이 안됩니다.)

Lua 문장의 마지막 구분

C언어는 문장의 마지막을 ; 을 붙이도록 되어있습니다. Lua는 ; 을 사용해도 되고 안해도 됩니다. 대부분 사용하지 않습니다.

Lua nil

C언어의 NULL은 0값을 지닙니다. 물론 C언와의 다른 느낌이지만, 이 부분은 java언어의 null 생각하면 됩니다. Lua에서는 비슷하게 nil 이 존재한다. 물론 C언와의 다른 느낌이지만 instance를 해제 할 때 nil로 초기화 합니다.

Lua if문

if exp then block {elseif exp then block} [else block] end
여기에서 { } 사이 내용은 0-N회 반복될 수 있다는 의미이고 [ ] 사이의 내용은 0-1 존재가능 하다는 의미 입니다.
괄호 { } 는 lua에서는 then end 로 사용됩니다.
C
#include <stdio.h>

int main(void) {
    int var1 = 1;
    if( var1==1 ) {
        printf("var1 = 1");
    }
    return 0;
}
Lua
var1 = 1
if( var1==1 ) then
    print("var1 = 1")
end

Lua elseif

if가 연속으로 있으면서 다른 조건을 가질때 C언어는 else if를 사용합니다. Lua에서는 붙여서 elseif를 사용합니다.
C
#include <stdio.h>
int main(void) {
 int a = 2;
 if(a==1){
     printf("1\n");
 }else if(a==2){
     printf("2\n");
 }
 return 0;
}
Lua
a = 2;
if(a==1) then
    print("1");
elseif(a==2) then
    print("2");
end

Lua if내에서 여러개의 조건을 가질때

if안에 조건이 여러개 있을때 사용하는 방법이 C언어와는 조금 차이를 보입니다. 아래 예제를 보시기 바랍니다. 두가지 차이가 있는데요. C언어에서 &&, || 연산자가 없고 and,or이 사용됩니다. 또하나의 차이점은 괄호의 위치입니다. C언어에서는 if문 안에 전체적으로 ()괄호가 사용되지만 Lua에서는 논리연산인 and, or 을 중심으로 작은 괄호들로 묶이게 사용해야 하며, 전체적으로 괄호를 묶어서 사용할 수 없습니다. 아래 예제에서 if((a==1) and (b==2)) 이런식으로는 사용할 수 없습니다.
C
#include <stdio.h>
int main(void) {
 int a = 1;
 int b = 2;
 if( a==1 && b==2){
     printf("Hi\n");
 }
 return 0;
}

Lua
a = 1;
b = 2;
if(a==1) and (b==2) then
    print("Hi");
end

Lua if문 내에서 같지 않는 조건 (!=)

!=, ~= 두개가 다르다
C
a!=b
#include <stdio.h>
int main(void) {
 int a = 1;
 int b = 2;
 if(a!=b){
     printf("diff\n");
 }
 return 0;
}
Lua
a~=b
a=1
b=2
if(a~=b)then
    print("diff")
end


Lua for

C언어 보다는 for loop가 단순하고 할 수 있는 조건이 제한적입니다. 마치 basic 언어의 for문을 보는듯 합니다. for 뒤에 변수명과 3개의 숫자가 들어가는데 초기값 최종값 증가하는 값입니다. C언어처럼 여러개를 넣을 수는 없습니다. 아래 C++예제는 for문 안에 int i=0를 넣었습니다. 참고로 C++언어에서는 해당 시점에 변수를 생성할 수 있습니다.
Lua에서 사용되는 변수는 for문 안에서만 사용되는 지역변수가 됩니다. 따라서 for문내에서 i값을 쓰더라도 for문을 벗어나면 기존의 i값이 변경이 되지 않습니다. 아래 예를 참고 하시기 바랍니다.

C++
#include <stdio.h>
#include <iostream>
using namespace std;

int main() {
    int i=100;
    for(int i=0;i<=10;i+=5){
 printf("%d\n",i);
    }
    printf("end:%d\n",i);
    return 0;
}
Lua
i=100
for i=0,10,5 do
    print(i)
end
print("end:"..i)
결과
0
5
10
end:100

Lua 입문 ( C언어 비교 ) (2)
http://swlock.blogspot.com/2017/01/lua-c-2.html

2016년 12월 4일 일요일

LuaJ 에서 java 메소드 호출

들어가기에 앞서
Lua 를 잘 모르시는 분은 따로 검색을 해보시기 바랍니다.

Java에서 Lua를 사용하기 위해서(왜 갑자기 시작했는지 모릅니다.) 검색을 시작 하였습니다.
그러다가 LuaJ를 발견하게 되었습니다. Lua는 C로 구현 되어있어서 아무래도 C와 연결하기가 굉장히 쉽게 되어 있는데 Java가 갑자기 하고 싶어 졌네요

LuaJ를 받아다가 library를 넣고 스크립트를 넣는것은 굉장히 단순합니다.
아래 주소에서 소스포함 library를 받으면 됩니다.
https://sourceforge.net/projects/luaj/
일반적으로 java se 버전을 사용하므로 라이브러리 폴더에 luaj-jse-3.0.1.jar 파일을 자신의 프로젝트에 복사해서 아래와 같은 예제를 사용하면 됩니다.

Run a script in a Java Application

A simple hello, world example in luaj is:
 import org.luaj.vm2.*;
 import org.luaj.vm2.lib.jse.*;

 Globals globals = JsePlatform.standardGlobals();
 LuaValue chunk = globals.load("print 'hello, world'");
 chunk.call();
 
Loading from a file is done via Globals.loadFile():
 LuaValue chunk = globals.loadfile("examples/lua/hello.lua");
Chunks can also be loaded from a Reader as text source
 chunk = globals.load(new StringReader("print 'hello, world'"), "main.lua");
or an InputStream to be loaded as text source "t", or binary lua file "b":
 chunk = globals.load(new FileInputSStream("examples/lua/hello.lua"), "main.lua", "bt"));
A simple example may be found in
 examples/jse/SampleJseMain.java
You must include the library lib/luaj-jse-3.0.1.jar in your class path.


아주 간단합니다. 하지만 Lua는 이럴려고 사용하는게 아니죠? 결국 자신이 필요한 함수를 만들어야 하는데요 즉 Lua script -> java 코드의 호출이 필요하게됩니다.
일주일 정도 LuaJ를 본 것 같습니다.
Readme.html에 있는 예제가 아무리해도 안되는겁니다.
그래서 중요한점을 빨간색으로 표시해보았습니다.

Libraries of Java Functions

When require() is called, it will first attempt to load the module as a Java class that implements LuaFunction. To succeed, the following requirements must be met:
  • The class must be on the class path with name, modname.
  • The class must have a public default constructor.
  • The class must inherit from LuaFunction.
If luaj can find a class that meets these critera, it will instantiate it, cast it to LuaFunction then call() the instance with two arguments: the modname used in the call to require(), and the environment for that function. The Java may use these values however it wishes. A typical case is to create named functions in the environment that can be called from lua.
A complete example of Java code for a simple toy library is in examples/jse/hyperbolic.java
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.*;

public class hyperbolic extends TwoArgFunction {

 public hyperbolic() {}

 public LuaValue call(LuaValue modname, LuaValue env) {
  LuaValue library = tableOf();
  library.set( "sinh", new sinh() );
  library.set( "cosh", new cosh() );
  env.set( "hyperbolic", library );
  return library;
 }

 static class sinh extends OneArgFunction {
  public LuaValue call(LuaValue x) {
   return LuaValue.valueOf(Math.sinh(x.checkdouble()));
  }
 }
 
 static class cosh extends OneArgFunction {
  public LuaValue call(LuaValue x) {
   return LuaValue.valueOf(Math.cosh(x.checkdouble()));
  }
 }
}
In this case the call to require invokes the library itself to initialize it. The library implementation puts entries into a table, and stores this table in the environment.
The lua script used to load and test it is in examples/lua/hyperbolicapp.lua
 require 'hyperbolic'

 print('hyperbolic', hyperbolic)
 print('hyperbolic.sinh', hyperbolic.sinh)
 print('hyperbolic.cosh', hyperbolic.cosh)

 print('sinh(0.5)', hyperbolic.sinh(0.5))
 print('cosh(0.5)', hyperbolic.cosh(0.5))
For this example to work the code in hyperbolic.java must be compiled and put on the class path.


중요한 사실은 eclipse를 이용하게되면 실행시 bin폴더에 출력 파일들이 생성되게 되고 클래스를 찾는 위치는 bin폴더 아래 위치에서 시작되게 됩니다.
따라서 위의 예제에서 hyperbolic 가 aaa패키지 아래에 있는 class라면 bin/aaa/hyperbolic.class파일이 생성이 될텐데요. lua에서 호출시 require 'aaa/hyperbolic' 이런식으로 호출 되어져야 합니다.

그리고 녹색으로 표현한 env.set( "hyperbolic", library ); 부분이 없다면 lua에서 hyperbolic 심볼을 사용할 수 없게 됩니다. 따라서 그때에는 아래와 같은 방식으로 호출 해야합니다.
abc=require 'aaa/hyperbolic'
print('sinh(0.5)', abc.sinh(0.5))

전체적으로 동작이 잘 안되는것 같다고 한다면 class파일을 여기저기 복사하면서 테스트 해보면 됩니다.




2016년 2월 12일 금요일

bit opration(비트연산) in corona sdk, Lua

bit 연산 때문에 여기저기를 찾아봤습니다.

Lua

Lua 의 낮은 버전에서는 원칙적으로 지원하지 않습니다. 5.2부터 지원한다고 합니다.
http://lua-users.org/wiki/BitwiseOperators
http://www.lua.org/manual/5.2/manual.html#6.7 <-여기 참고 하면됩니다.
> print(bit32.bor(3,1))
3
> print(bit32.band(3,1))
1
5.1이하 버전에서 사용하려면 라이브러리를 사용하면 됩니다.

Corona SDK

Corona SDK의 경우 Lua 5.1 기반으로 되어있기 때문에 지원하지 않습니다.
따라서 다른 라이브러리를 사용하면되는데 Corona SDK에서 사용하려면 native 언어로 된것은 일반 사용자가 사용이 안되므로 Lua 언어로된 library를 사용해야합니다.

적절한것은 아래 나온 링크들입니다.

Pure Lua implementations:

그중 [bit.numberlua] 에 사용해 보았습니다.
https://github.com/davidm/lua-bit-numberlua/ 여기에서 받을 수 있습니다.
https://github.com/davidm/lua-bit-numberlua/blob/master/lmod/bit/numberlua.lua 여기에 있는 lua 파일을 다운로드 받아서 자신의 project에 넣고 다음과 같이 사용하면 됩니다.

local bit = require 'numberlua'
print(bit.bor(1,2,3))


2016년 1월 17일 일요일

Lua 필수 알고 있어야 할 것 정리

Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua Lua

table의 index
Lua에서는 특별히 지정하지않으면 index는 1부터 시작됨(C 언어와의 차이점)
> M={{1,2,3},{2,3,4,6}}
> print(M[0])
nil
> print(M[1])
table: 008BA018
> print(M[1][1])
1
>

table의 갯수 구하기 
'#' 을 붙여준다.
> M={{1,2,3},{2,3,4,6}}
> print(#M)
2
> print(#M[1])
3
> print(#M[2])
4

random 함수
랜덤 함수를 사용전에는 math.randomseed( os.time() ) 호출 해주도록 한다. 항상은 아니고 pc시작시 한번 호출해 주도록 한다. seed를 초기화해서 매번 다른 난수를 생성시키도록 한다.

random 함수
math.random(N,M) 주로 이걸 사용하도록 한다. N과 M사이의 숫자를 생성한다.
math.random(1,M) => math.random(M) 동일함
local random = math.random
random(M)



2016년 1월 15일 금요일

루아(Lua)에서 colon(:) 과 dot(.) 연산자 이해


사용하면서도 항상 헷갈리는게 colon(:) 과 dot(.) 였습니다. 책을 봐도 이해가 안되는 말뿐이고 이걸 언젠가는 완벽 이해 해야겠다고 결심했습니다.

아래 링크를 보면 외국인들도 헷갈리긴 마찬가지 인가 보네요.

https://coronalabs.com/blog/2015/12/01/tutorial-understanding-the-colon-vs-dot-operator/

CORONA with Lua -원강민 지음- 책 78 page에 보면 차이점이 나오긴 합니다.
둘의 차이는 하나입니다. :으로 된 함수는 내부에 self라는 변수가 자동으로 생성되는 것인데요. 해당 객체 자신을 참조합니다.
예제로 배우는 프로그래밍 루아 -한빛미디어- 책 76 page에는 아래와 같이 나옵니다.
즉, ':'정의를 하면 'self'를 생략할 수 있습니다.

이것을 정리해보도록 하겠습니다.
아래와 같은 예제를 사용했을때 결과를 한번 보시죠
local object = {}

function object.dotMethod( parameter1, parameter2 )
    print( self.someNumber )
end

function object:colonMethod( parameter1, parameter2 )
    print( self.someNumber )
end

object.someNumber = 10
object.dotMethod( "Hello", "World" )    -- Dot method called with dot operator
object:colonMethod( "Hello", "World" )  -- Colon method called with colon operator
Running this code, you can see that the result in the console is:
nil
10
C++ 언어와 비교해 보겠습니다.


#include <iostream>
#include <stdio.h>
using namespace std;

class Object
{
public:
 int someNumber;
 Object()
 {
  this->someNumber = 0;
 }
 void Method();
};

void Object::Method()
{
 printf("%d\n",this->someNumber);
}

int main() {
 Object object1;
 object1.Method();
 object1.someNumber = 10;
 object1.Method();
 
 Object *object2 = new Object();
 object2->Method();
 object2->someNumber = 10;
 object2->Method();
 delete object2;
 return 0;
}

결과
Success time: 0 memory: 3460 signal:0
0
10
0
10


정리하자면 
Lua에서의 self는 타언어 (Java,C++)에서 this와 동일하다.
Lua의 method 내에서 self를 사용할 수 있는 조건은 메소드를 ':'을 사용해서 호출할 때이다.

C++ 언어에서 보면 객체내에서는 this사용이 자유롭다고 보면 됩니다. 하지만 lua는 : 로 호출할때만 내부에서 self 를 이용 가능합니다.
Lua에서 ":" , "." 메소드를 어떻게 만들었냐에 따라 다릅니다.
일반적으로 corona sdk의 기본 library함수는 "."을 사용합니다.

타언어와 비교를 했는데도 어렵다면 객체 지향에 대해서 이해가 필요하고요, 잘모르겠다고 판단되면 . 로 호출되는 대부분의 함수들은 corona sdk의 기본 함수들입니다. 그리고 그외에 소스가 있는것들을 자세히 살펴보면 개발자가 : 사용해서 정의가 되어있는지 . 로 사용하여 정의가 되어있는지에 따라서 호출 방법이 달라지게 됩니다.

string 길이를 구하는데 class 정보가 필요하지 않기 때문에 "."로 되어있나 봅니다.

local length = string.len( "Hello World" )