Scite Lua Dll

lua-users home
wiki

为 SciTE 创建自定义 Lua Dll

以下是我找到的创建可使用 loadlib() 加载的完全功能* Win32 DLL 的解决方案。

版本说明: 此代码基于旧版本的 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 版本,则应使用此选项。

请参阅 创建二进制扩展模块 以构建 Lua 和您的 Dll。

您必须将“lua.dll”复制到您的 <scite> 文件夹中,以及 SciTE.exe,才能使您的 Dll 工作。

在 Lua 中加载您的 Dll

将“mydll.dll”复制到您的 <scite> 文件夹中,以及 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)

我没有创建 dll 的 Makefile,我使用批处理文件

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 日

使用 MinGW DLL 而不使用单独的 Lua 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 的提示,您可以构建您的库,将来自 Scite 源代码的 Lua 包含目录提供给编译器,并将 "SciTE.lib" 文件提供给链接器。

在您的 Lua 代码中使用库也非常简单。将 "mydll.dll" 复制到您的 <scite> 文件夹中,以及 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;
}

--由 Maciej Radziejewski 为 Scite 1.74 和 Lua 5.1 更新


RecentChanges · preferences
编辑 · 历史
最后编辑于 2008 年 10 月 10 日下午 7:47 GMT (差异)