2013-10-17 21 views
4

從文檔:http://luajit.org/running.html運行luajit目標文件由C

luajit -b test.lua test.obj     # Generate object file 
# Link test.obj with your application and load it with require("test") 

但沒有解釋如何做這些事情。我想他們假設任何使用Lua的人也是C程序員,而不是我的情況!我可以得到一些幫助嗎? GCC爲例。

我也想做同樣的事情,除了從C字節數組頭。我也找不到這方面的文檔。

luajit -bt h -n test test.lua test.h 

這將創建頭文件,但我不知道如何從C運行它。謝謝。

+0

您應該能夠使用'luaL_loadstring'加載該C數組。一旦將函數返回到堆棧中,您可以使用'call'或'pcall'來執行它,或者如果您稍後需要它,可以將其保存到'package.preload'表中,具體取決於您想要的內容去做。 – greatwolf

回答

7

的基本用法如下:

  • 使用luajit
  • #include那那將被引用其符號源文件(一個或多個)在報頭生成頭文件
  • 編譯源成一個可運行的可執行文件或用於lua的共享二進制模塊,具體取決於您的使用情況。

這裏的一個最小的例子來說明:

test.lua

return 
{ 
    fooprint = function (s) return print("from foo: "..s) end, 
    barprint = function (s) return print("from bar: "..s) end 
} 

test.h

// luajit -b test.lua test.h 
#define luaJIT_BC_test_SIZE 155 
static const char luaJIT_BC_test[] = { 
27,76,74,1,2,44,0,1,4,0,2,0,5,52,1,0,0,37,2,1,0,16,3,0,0,36,2,3,2,64,1,2,0,15, 
102,114,111,109,32,102,111,111,58,32,10,112,114,105,110,116,44,0,1,4,0,2,0,5, 
52,1,0,0,37,2,1,0,16,3,0,0,36,2,3,2,64,1,2,0,15,102,114,111,109,32,98,97,114, 
58,32,10,112,114,105,110,116,58,3,0,2,0,5,0,7,51,0,1,0,49,1,0,0,58,1,2,0,49,1, 
3,0,58,1,4,0,48,0,0,128,72,0,2,0,13,98,97,114,112,114,105,110,116,0,13,102, 
111,111,112,114,105,110,116,1,0,0,0,0 
}; 

runtest.cpp

// g++ -Wall -pedantic -g runtest.cpp -o runtest.exe -llua51 
#include <stdio.h> 
#include <assert.h> 

#include "lua.hpp" 
#include "test.h" 

static const char *runtest = 
"test = require 'test'\n" 
"test.fooprint('it works!')\n" 
"test.barprint('it works!')\n"; 


int main() 
{ 
    lua_State *L = luaL_newstate(); 
    luaL_openlibs(L); 

    lua_getglobal(L, "package"); 
    lua_getfield(L, -1, "preload"); 
    // package, preload, luaJIT_BC_test 
    bool err = luaL_loadbuffer(L, luaJIT_BC_test, luaJIT_BC_test_SIZE, NULL); 
    assert(!err); 

    // package.preload.test = luaJIT_BC_test 
    lua_setfield(L, -2, "test"); 

    // check that 'test' lib is now available; run the embedded test script 
    lua_settop(L, 0); 
    err = luaL_dostring(L, runtest); 
    assert(!err); 

    lua_close(L); 
} 

這是非常直接的。本示例採用字節碼並將其放入此程序的lua環境的package.preload表中。其他lua腳本可以通過執行require 'test'來使用它。在runtest嵌入式LUA源不正是這個和輸出:

from foo: it works! 
from bar: it works! 
+0

太棒了,謝謝!這是我需要知道的,luaL_loadbuffer。你能告訴我,如果使用普通的luac可以做到同樣的事情嗎? – Matthew

14

main.lua

print("Hello from main.lua") 

app.c

#include <stdio.h> 

#include "lua.h" 
#include "lauxlib.h" 
#include "lualib.h" 

int main(int argc, char **argv) 
{ 
    int status; 
    lua_State *L = luaL_newstate(); 
    luaL_openlibs(L); 
    lua_getglobal(L, "require"); 
    lua_pushliteral(L, "main"); 
    status = lua_pcall(L, 1, 0, 0); 
    if (status) { 
    fprintf(stderr, "Error: %s\n", lua_tostring(L, -1)); 
    return 1; 
    } 
    return 0; 
} 

Shell命令:

luajit -b main.lua main.o 
gcc -O2 -Wall -Wl,-E -o app app.c main.o -Ixx -Lxx -lluajit-5.1 -lm -ldl 

用LuaJIT include和庫目錄替換-Ixx-Lxx。如果您已將它安裝在/usr/local(默認值)中,那麼大多數GCC安裝會在沒有這兩個選項的情況下找到它。

第一個命令將Lua源代碼編譯爲字節碼並將其嵌入到目標文件main.o中。

第二個命令編譯並鏈接最小的C應用程序代碼。請注意,它也鏈接在嵌入式字節碼中。 -Wl,-E是必需的(在Linux上)從可執行文件導出所有符號。

現在移動原main.lua離開(以確保它的真正運行嵌入式字節碼,而不是Lua的源代碼文件),然後運行你的應用程序:

mv main.lua main.lua.orig 
./app 
# Output: Hello from main.lua 
+0

太棒了!謝謝! luac也可以生成.o文件嗎? – Matthew

+0

不,只有'luajit -b'可以一步完成。有像'bin2c'這樣的第三方工具可以幫助簡單的Lua。看看[其他答案](http://stackoverflow.com/a/19426724/1657919)爲一般方法。 –

+0

有沒有辦法像'assert(loadfile(「main」))'而不是'require(「main」)''做些事情? 'loadfile'似乎沒有找到像'require'這樣的鏈接模塊,而只是運行搜索文件。我試圖將參數(從app.c使用argv)傳遞給鏈接模塊,並且不能使用'require',因爲它不會返回模塊作爲我可以像'loadfile'那樣調用的函數。 – ckemper