Scite Lua Dll

lua-users home
wiki

為 SciTE 建立自訂 Lua Dll

以下是找到建立 Win32 DLL 並使用 loadlib() 載入的完整功能解決方案。

版本公告:程式碼建構於舊版 Lua。Lua 5.1. 使用 package.loadlib。

* 完整功能是指載入的 DLL 能夠定義 Lua 腳本可存取的全域物件和函數。

若要順利運作,您必須選擇下列選項:

1. 建立特殊的 SciTE 組譯 (這其實很容易)
2. 加入另一個 lua.dll (如果您想使用正式的 SciTE 組譯,建議這麼做)

編寫 Dll

這個範例 Dll 會加入一個新的元表「mydll」,其中包含兩個函數

Dll 來源「mydll.c」

#include <windows.h>
#include "lauxlib.h"

/**
 * @method OK MessageBox
 * @param message
 * @param title
 * @return selection
 */
int mydll_msgbox(lua_State* L)
{
	const char* message = luaL_checkstring(L, 1);
	const char* caption = luaL_optstring(L, 2, "");
	int result = MessageBox(NULL, message, caption, MB_OK);
	lua_pushnumber(L, result);
	return 1;
}

/**
 * @method OK / CANCEL MessageBox
 * @param message
 * @param title
 * @return selection
 */
int mydll_confirm(lua_State* L)
{
	const char* message = luaL_checkstring(L, 1);
	const char* caption = luaL_optstring(L, 2, "");
	int result = MessageBox(NULL, message, caption, MB_OKCANCEL);
	lua_pushnumber(L, result);
	return 1;
}

// methods table
static const luaL_reg mydll_methods[] = {
  {"confirm", mydll_confirm},
  {"msgbox", mydll_msgbox},
  {0, 0}
};

/**
 * Register objects and functions
 */
int __declspec(dllexport) libinit (lua_State* L)
{
	// create methods table, add it to the globals
	luaL_openlib(L, "mydll", mydll_methods, 0);
	// create metatable, and add it to the Lua registry
	luaL_newmetatable(L, "mydll");
	return 0;
}

第一個選項:客製化的 SciTE 組譯

下載 SciTE 來源並修改「<scite_src>\scite\lua\include\lua.h」,第 94 行,以讓 SciTE 為您的 Dll 匯出 Lua API

/* mark for all API functions */
#ifndef LUA_API
// was: #define LUA_API       extern
#define LUA_API       __declspec(dllexport)
#endif

這樣就完成了,非常簡單 (感謝 SteveDonovan 提供這個秘訣,謝謝您)。

現在組譯 scintilla 和 scite,我在使用 Borland C++ 編譯器

cd <scite_src>\scintilla\win32
make -f scintilla.mak

cd <scite_src>\scite\win32
make -f scite.mak
implib SciTE SciTE.exe

現在應該會有「bin」資料夾中的「SciTE.lib」。您可以組譯 Dll 了

cd <mydll_src>\
bcc32 -w -tWD -I..\scite\lua\include -DLUA_API=__declspec(dllimport) ..\scite\bin\SciTE.lib mydll.c

第二個選項:加入另一個 lua.dll

如果您想依賴未匯出 Lua API 的正式 SciTE 組譯,應該使用這個選項。

參閱 CreatingBinaryExtensionModules 以組譯 Lua 和您的 Dll。

您必須將「<scite>」資料夾中的「lua.dll」與 SciTE.exe 一起拷貝,Dll 才會運作。

在 Lua 中載入您的 Dll

將「<scite>」資料夾中的「mydll.dll」與 SciTE.exe 一起拷貝。

在您的 Lua 腳本 (例如 SciTEStartup.lua) 中加入這段程式碼

-- load your custom Dll
libinit = loadlib(props['SciteDefaultHome'].."/mydll.dll", "libinit")
if libinit then libinit()
else
	print ("Error: unable to load mydll.dll")
end

-- test your Dll
if mydll then
	mydll.msgbox("Hello World!", "Hello")
end

--Philippe

使用 MinGW

MinGW 沒有 implib 工具程式,或至少無法辨識,所以我必須建立一份 Lua 程式碼的 .dll,才能建立我的 dll。

我相信有些來自 Lua 的小修訂與標準 Lua 釋出版本不同,所以我選擇將 dll 命名為 SciTELua.dll

在 SciTE\Win32\Makefile 內

# after "PROGSTATIC = ../bin/Sc1.exe" I added 
LUA_DLL=../bin/SciTELua.dll
LUA_DLL_LIB=../bin/lscitelua.a
LUA_DLL_DEF=../bin/scitelua.def

# after "LUA_CORE_OBJS" and "LUA_LIB_OBJS" are defined I added
LUA_DLL_OBJS := $(LUA_CORE_OBJS) $(LUA_LIB_OBJS)

# I modified "ALL" to be
ALL:	$(PROG) $(PROGSTATIC) $(DLLS) $(PROPS) $(LUA_DLL) $(LUA_SCRIPTS)

#this is at the bottom, below "SciTEBase.o: $(OTHER_OBJS)"
$(LUA_DLL): $(LUA_DLL_OBJS)
	$(DLLWRAP) --no-idata4 --no-idata5 --target i386-mingw32 -mno-cygwin --output-lib $(LUA_DLL_LIB)  --output-def $(LUA_DLL_DEF) -o $(LUA_DLL) $(LUA_DLL_OBJS)

我沒有建立 Makefile 來建立我的 dll,我是使用批次檔

SET OUTDIR=../scite/bin
SET OUTFILE=aprillua

gcc 2>&1 -mno-cygwin -DLUA_API=__declspec(dllimport) -c -Wall -I../scite/lua/include aprilluadll.c
dllwrap 2>&1 --no-idata4 --no-idata5 --target i386-mingw32 -mno-cygwin --output-def %OUTDIR%/%OUTFILE%.def --output-lib %OUTDIR%/l%OUTFILE%.a -o %OUTDIR%/%OUTFILE%.dll aprilluadll.o -L%OUTDIR% -lscitelua -mwindows

我的測試 dll 是根據 msgbox() 和 confirm() 函數的程式碼,即使我也寫了 getsavefilename(),這是 GetSaveFileName?() Win32 API 的連結。

MinGW 並未在初始化函式庫名稱前加上底線,所以我的 SciTE 啟動腳本為

local libinit = loadlib(props.SciteDefaultHome .. "\\aprillua.dll", "libinit")

--April White

對於您的函式庫 libinit() 方法,使用這個來呼叫 luaL_openlib()

// create methods table, add it to the globals
const char* tblname = luaL_optstring(L, 1, "mydll" );
luaL_openlib(L, tblname, dll_methods, 0);

讓 libinit() 可以接受一個選擇性參數作為表格名稱。因此,您的 Lua 程式碼可能讀取為

local libinit = loadlib(props.SciteDefaultHome .. "\\test.dll", "libinit")
if libinit then
	libinit() -- defaults to mydll
else
	alert("Error: unable to load " .. props.SciteDefaultHome .. "\\test.dll" )
end

local libinit = loadlib(props.SciteDefaultHome .. "\\test.dll", "libinit")
if libinit then
	libinit( "Aprilz" ) -- creates the table as Aprilz
else
	alert("Error: unable to load " .. props.SciteDefaultHome .. "\\test.dll" )
end
--April White,2005 年 9 月 24 日

不使用獨立的 Lua DLL 而使用 MinGW DLL

事實上,可以把 MinGW DLL 連結到 SciTE 的修補版本。為此,您將需要一個包含所有 lua 函數的 scite.def 檔案。

LIBRARY "SciTE.exe"
EXPORTS
luaL_addlstring
luaL_addstring
luaL_addvalue
...
我已將 scite.def 版本放在檔案管理員的 Files:wiki_insecure/editors/SciTE/scite.def 中。

要從 scite.def 建立匯入函式庫,請使用 dlltool

dlltool -d scite.def -l scite.la
然後建立您的 DLL(例如優良的 LuaFileSystem),只需使用
gcc -shared -I..\scite\lua\include lfs.c -o lfs.dll scite.la
--Steve Donovan,2007 年 7 月 2 日

針對 SciTE 1.74 或後續版本和 Lua 5.1 更新

使用 Visual Studio 2005 和 SciTE 1.74 或後續版本,建置函式庫的流程非常簡單,因為看起來 SciTE 的官方原始碼已被修補,以適用於上述第一個選項。

您需要取得 Scite 的原始碼並重建。函式庫檔案「SciTE.lib」應會產生,您可以在二進位檔案中找到它。我不知道其他編譯器是否亦適用。 現在,依照 Steve Donovan 的提示,您可以建立函式庫,提供 Lua 包含目錄從 Scite 原始碼到編譯器,以及「SciTE.lib」檔案給連結器。

在您的 Lua 程式碼中使用函式庫也很簡單。在您的 <scite> 資料夾中將「mydll.dll」連同 SciTE.exe 一起複製。然後將此程式碼放入您的 Lua 啟動指令碼

-- load your custom Dll
require 'mydll'

-- test your Dll
if mydll then
        mydll.msgbox("Hello World!", "Hello")
end

因此,註冊 Lua 5.1 物件和函數的更新函數為

/**
 * Register objects and functions
 */
int __declspec(dllexport) luaopen_mydll (lua_State* L)
{
	// Add the methods table to the globals
	luaL_register(L, "mydll", mydll_methods); 
	return 1;
}

--針對 Scite 1.74 和 Lua 5.1 更新,Maciej Radziejewski


最近異動 · 偏好設定
編輯 · 歷程
最後編輯時間為 2008 年 10 月 10 日下午 7:47 GMT (diff)