20130128-LUACOM-IDL-VBS

    LUA很好用,在Windows下COM是老大,如果能结合它们的功能,那会是比较酷的。LuaCOM库(目前版本1.4)非常好的扮演了这个牵线搭桥的角色,本文不讨论Luacom的各项功能,大家可下载LuaCOM User Manual手册作全面的了解。这面只是举一个HelloWorld的例子,以及在实现这个例子过程的一点教训。网上关于这方面的详细例子不多(也可能是本人的搜索方法不是很对),基本上找不着HellowWorld档次的例子,所以感觉有必要写一个博客,与有兴趣的读者共享,也做为自己的笔记。

    准备必要的工具,如果有安装了VS IDE那是最好的,除了MIDL.exe之外还有Visual Studio Command Prompt (2010)都可以轻松获得。再就是Lua.exe和LuaCOM.dll,这里有个教训就是Lua.exe和LuaCOM.dll的版本要相适应(LuaCOM.dll最好是1.4版本的,1.3好像测试无法正常通过,也没仔细去研究,用上1.4的就正常了,如果大家能在1.3下通过下边这个例子,请给个跟贴,谢谢)。

    准备一个idl文件,然后使用MIDL.exe生成一个tlb文件,文件名分别为test.idl和test.tlb。

test.idl

//VBScript and JScript do not support [in,out], use [in,out] or [out,retval] 
//import "unknwn.idl";

[
	uuid(991AB5E0-97C4-4ecc-9926-D76038C517A1),
	version(1.0)
]
library TEST
{
	importlib("STDOLE2.TLB");
	
	[
		object,
		uuid(1AB5DCC7-11F7-441f-962C-57A528F85F47),
		dual,
		oleautomation,
		version(1.0),
		helpstring("luacom interface implement test 1.0")
	]
	interface ITest : IDispatch {
		 void Version([in,out]short* major, [in,out]short* minor);
	};

	[uuid(340DFD25-59B2-49b4-A693-A7B19A13FD42)]
	coclass Test {
		[default] dispinterface ITest;
	}
};

    本人不熟悉VBScript和JScript,一开始参数只是指定[out],结果一定得不到正常的返回结果(没有返回结果),在网上搜了搜才知道不支持[out]参数,如果在LuaCOM,这样的参数是能正常返回的。

    准备一个实现COM的Lua脚本,在LuaCOM手册上有一个,在这里只是稍做改动,以实现上面的ITest接口。

testobj.lua

--This is the implementation of the COM object
local LOON_DIR = os.getenv("loon");
package.cpath = LOON_DIR .. [[\..\lua\?.dll]]
require "luacom"
path_to_script = LOON_DIR .. [[\..\lua\idl\]]

------------------------------------------------------------------------------

TestObj = {}
function TestObj:Version(a,b)
	return 123+a,455+b;
end

------------------------------------------------------------------------------
COM = {}

function COM:StartAutomation()
	--print("testobj.lua > StartAutomation");
	-- Creates the object using its default interface
	COMAppObject, events, e = luacom.NewObject(TestObj, "TEST.Test");
	--print("testobj.lua > " .. tostring(COMAppObject), events, e);
	-- This error will be caught by detectAutomation
	if COMAppObject == nil then
		error("NewObject failed: " .. e);
	end
	-- Exposes the object
	cookie = luacom.ExposeObject(COMAppObject);
	if cookie == nil then
		error("ExposeObject failed");
	end
	--print("testobj.lua > ookie=" .. tostring(cookie));
end

function COM:Register()
	-- Fills table with registration information
	local reginfo = {};
	reginfo.VersionIndependentProgID = "TEST.Test";
	reginfo.ProgID = reginfo.VersionIndependentProgID .. ".1";
	reginfo.TypeLib = "test.tlb";
	reginfo.CoClass = "Test";
	reginfo.ComponentName = "Test Component use luacom";
	reginfo.Arguments = "/Automation";
	reginfo.ScriptFile = path_to_script .. "testobj.lua";
	-- Stores compnent information in the registry
	local res = luacom.RegisterObject(reginfo);
	if res == nil then
		error("RegisterObject failed!");
	end
end

function COM:UnRegister()
	-- Fills table with registration information
	local reginfo = {};
	reginfo.VersionIndependentProgID = "Test.Test";
	reginfo.ProgID = reginfo.VersionIndependentProgID .. ".1";
	reginfo.TypeLib = "test.tlb";
	reginfo.CoClass = "Test";
	-- removes compnent information from the registry
	local res = luacom.UnRegisterObject(reginfo);
	if res == nil then
		error ("UnRegisterObject failed!");
	end
end

-- starts automation server
return luacom.DetectAutomation(COM);
--xCom = { luacom.DetectAutomation(COM); };
--for k,v in pairs(xCom) do
	--print(k,v);
--end
--return unpack(xCom);

    执行2个命名,一个是生成test.tlb,另一个是将COM注册到注册表中,执行完后,大家可到注册表中去看看它的注册内容

maketlb.bat

@REM SET MIDLDir="c:\Program Files\Microsoft SDKs\Windows\v7.0A\bin"
SET MIDLDir="d:\Program Files\Microsoft SDKs\Windows\v6.0A\bin"
SET IDLFile="%loon%\..\lua\idl\test.idl"
SET TLBFile="%loon%\..\lua\idl\test.tlb"

@SET PATH="%loon%\..\lua\";%PATH%
chdir /d %MIDLDir%
midl.exe "%IDLFile%" /tlb "%TLBFile%" /out "%loon%\..\lua\"

chdir /d "%loon%\..\lua\idl"
lua testobj.lua /register

    实现(纯Lua代码)和注册已经完成,下面就可以使用这个COM接口了。这里分别是用LuaCOM脚本和VBS脚本来调用它。

test.lua

package.cpath = os.getenv("loon") .. [[\..\lua\?.dll]]
require "luacom"

obj = {};
print("testlua.lua > luacom=" .. tostring(luacom));
x = luacom.CreateObject("TEST.Test");
print("testlua.lua > comobj=" .. tostring(x));
for k,v in pairs(x) do
	print(k,v);
end
print(x:Version(4,5));

test.vbs

ON ERROR RESUME NEXT
Set x = CreateObject("TEST.Test")
Dim a,b
a=4
b=5
x.Version a,b
MsgBox "Version: "+CStr(a)+"."+CStr(b), vbOK 

    可以看到输出结果 127和460,说明输进去的接收到了,修改后返回也正确接收到了。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值