วันอังคารที่ 8 กรกฎาคม พ.ศ. 2557

Upgrade LUA skill ด้วยการเขียน C module

มา upgrade LUA skill กัน ด้วยการเขียน LUA ไปเรียก module ที่เขียนด้วย C



ส่วนจะควรจะเรียกใช้ หรือเขียนอะไรด้วย LUA เขียนอะลัวด้วยไร ค่อยไปหาคำตอบกันเอง เช่น มีเพื่อนผมกลุ่มนึง เขียน Socket library เป็น Core module แล้ว Binding เขากับ LUA จากนั้นก็ใช้ LUA เขียน Server ทั้งตัว ก็มี

จาก Document พบว่า LUA ใช้ lua_State ในการส่งผ่าน parameters จาก LUA script ไปยัง C module ("Shared Object", file.so)  โดยมีรูปแบบมาตรฐานเริ่มต้นดังนี้

#include <lua.h> 
#include <lauxlib.h>

#include <lualib.h> 

int luaopen_cprime(lua_State *L){
   return 0;
}

ผมตั้งชื่อ library ตัวนี้ว่า cprime โดยวางแผนว่า ในนั้นจะมี function ง่ายๆ ในการตรวจสอบว่า ตัวเลขที่ส่งเข้ามาเป็น Prime Number หรือไม่ 

จากนั้นก็เพิ่ม function isprime สำหรับการตรวจสอบ Prime Number เข้าไป

static int isprime(lua_State *L) {
   int number = lua_tointeger(L, -1);
   for (int i = 2; i < number; i++) {
      if (number % i == 0 && i != number) {
         lua_pushnumber(L, 0);
         return 1;
      }
  }
  lua_pushnumber(L, 1);
  return 1;
}

อย่างที่ได้บอกไปแล้วว่า LUA ใช้ lua_State เป็น structure ในการส่งผ่าน parameters ระหว่าง LUA และ external module รวมถึงภายใน external module เอง 

ถ้าดูจาก function isprime ด้านบน lua_State จะเป็นทำหน้าที่ส่งผ่าน parameters ของ function isprime ทั้งหมด กรณีนี้ ผมส่ง integer เข้ามาตัวเดียว ซึ่งเราจะทำการดึง integer ที่ส่งผ่านเข้ามาใน isprime ด้วย lua_tointeger(L, -1);

lua_Integer lua_tointeger (lua_State *L, int index);

จากนั้นก็ตรวจสอบดูว่า ค่าที่ส่งเข้ามานั้นเป็น Prime Number หรือไม่ ถ้าใช่ เราก็ทำการ push 1 เข้าไปใน lua_State ด้วย lua_pushnumber(L, 0);

void lua_pushnumber (lua_State *L, lua_Number n);

ถ้าไม่ใช่ก็ push 0 เข้าไปแทน

แต่ก่อนจะใช้ isprime ได้ต้องทำการ register method isprime ให้ LUA รู้จักก่อนโดยการเรียก  (เราอาจเปลี่ยนชื่อ isprime เป็นอย่างอื่นก็ได้ ด้วยการแก้ที่ paraemters ที่สอง เช่น "fprime" เป็นต้น)

lua_register(L,"isprime",isprime); 

ใน luaopen_cprime(...); ซึ่งหน้าตาของ cprime.c จะเป็นแบบนี้

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>

static int isprime(lua_State *L) {
  int number = lua_tointeger(L, -1);
  for (int i = 2; i < number; i++) {
    if (number % i == 0 && i != number) {
      lua_pushnumber(L, 0);
      return 1;
    }
  }
  lua_pushnumber(L, 1);
  return 1;
}

int luaopen_cprime(lua_State *L){
  lua_register(L,"isprime", isprime);
  return 0;
}

จากนั้น compile 

$ gcc -Wall -shared -fPIC -o cprime.so -I/usr/include/lua5.1 -llua5.1 cprime.c

(อย่าลืมติดตั้ง Lua5.1 ก่อนนะจ๊ะ)

แล้วเราก็มาสร้าง prime.lua file เพื่อเรียกใช้ isprime ของเรา หน้าตาจะเป็นแบบนี้ครับ

#!/usr/bin/lua

require("cprime")
print(isprime(13))
print(isprime(12))

แล้วเรียก

$ lua prime.lua
1
0

ประมาณนี้...ครับ :-)



ไม่มีความคิดเห็น:

แสดงความคิดเห็น