View Full Version : How to use / reference external DLL Library in LUA
nurowolf
September 22nd, 2006, 12:32 AM
Hi All
I am looking to start playing around with trying to get Girder to work with Meedio. Iwas hoping to make use of the Meedio.Client Library to send & Receive messages, but I need to make this library available to LUA.
Can somebody point we in the correct direction on how to do this?
Is there a USE or INclude type statement in LUA?
nurowolf
September 22nd, 2006, 01:10 AM
So I have worked out that I need to use the luacom library. SO am making progress.
This is what I am got so far.
meedio = luacom.CreateObject("MeedioClient.MeedioPluginClient")
assert(meedio)
Now I need to connect to Meedio, but I need to pass a handle as part of the call.
Here is the VB code to do this.
Result = Meedio.Connect("localhost", 7500, "password", Handle.hWnd, WM_USER + 10)
How would this with LUA?
nurowolf
September 22nd, 2006, 02:04 AM
I think I am getting closer to connecting to meedio, but am getting an error. This is what I am so far.
Result = False
meedio = luacom.CreateObject("MeedioClient.MeedioPluginClient")
assert(meedio)
myhandle,myerr = win.FindWindow('TApplication','Girder 4.0')
Result = meedio.Connect('localhost', 7500, 'password', myhandle, 1040 )
if not Result then
print('no connection')
else
print('connection made')
end
1040 is suppose to be WM_USER + 10, but I am having trouble with hex values, so tried the Decimal alternative.
Anyway I get the following error.
COM error:(.\src\library\tLuaCOM.cpp,403):Type mismatch.
stack traceback:
[C]: in function `Connect'
[string "MeedioClient.gml:\New\Scripting"]:10: in main chunk
The Meedio API says the following
Connect(Host As String, Port As Long, Password As String, Window As Long,
MessageID As Long) As Boolean
Tries to connect to Meedio and returns TRUE if successful.
-Host: Host name or IP address of the machine running Meedio
-Post: Port to connect to (Meedio, by default, listens to port 7500)
-Password: Password required to authenticate. It must match the password entered in Meedio's configuration application
-Window: hWnd of the window that will receive the notification messages
-MessageID: Message the Meedio Client Library will post to the specified hWnd to notify there are incoming Meedio messages
ANybody got any ideas where I am going wrong???
nurowolf
September 22nd, 2006, 02:10 AM
OK - worked it out.
I had
Result = meedio.Connect('localhost', 7500, 'password', myhandle, 1040 )
and I should have had
Result = meedio:Connect('localhost', 7500, 'password', myhandle, 1040 )
nurowolf
September 22nd, 2006, 03:03 AM
Now a critical question. How do I get GIRDER to act when ever a new message arrives on the Message Que I jsut created above.
I can manually process a Message by manually triggering a scripting event, but how would I have Girder just sit and wait for a message & then process it????
Promixis
September 22nd, 2006, 07:59 AM
is there documentation on using that com object?
nurowolf
September 22nd, 2006, 08:21 AM
http://www.meedio.com/mdn/index.php?title=Meedio_Client_Library This gives you a list of methods.
http://www.meedio.com/mdn/index.php?title=Using_the_Meedio_Client_Library_wi th_Visual_Basic_6 This gives you a VB6 example
It talks about using a 'hook' to monitor for new messages - but since I am trying to use LUA - I am not sure if it is relevant.
Promixis
September 22nd, 2006, 08:46 AM
hm, this doesn't look easy :(
the best solution I can see is to create a timer that calls the getnextmessage method every 100ms or so.
the hook is the best way to do this but is not readily doable.
nurowolf
September 22nd, 2006, 08:06 PM
OK. WIll try the timer approach.
Since this will need to be running in the background all the time - I guess I should also start looking into coroutines?
Promixis
September 23rd, 2006, 11:51 AM
no need for coroutines with the timer. see gir.CreateTimer.
nurowolf
September 30th, 2006, 03:55 AM
Finally Got round to trying this out, but I can only get the code to execite once when I use the gir.CreateTimer code.
This is my code
function mytest()
test = meedio:GetNextMessage()
if test==nil then
print('No message')
else
print(test.Subject)
print(test.Count)
i = test.Count
i = i-1
for v = 0, i, 1 do
--print(test.Count)
print('key: '..tostring(test:Keys(v))..' Value: '..tostring(test:Values(v)))
end
end
end
Result = False
meedio = luacom.GetObject("MeedioClient.MeedioPluginClient")
if meedio then
print('Meedio already connect')
else
meedio = luacom.CreateObject("MeedioClient.MeedioPluginClient")
--assert(meedio)
myhandle,myerr = win.FindWindow('TApplication','Girder 4.0')
print(myhandle)
Result = meedio:Connect('localhost', 7500, 'password', myhandle, 1040 )
if not Result then
print('no connection')
else
print('connection made')
end
end
meedio:AddSubjectMask('*')
meediotimer = gir.CreateTimer("", mytest(meedio),"", true, true)
meediotimer:Arm(100)
function mytest(meedio)
test = meedio:GetNextMessage()
if test==nil then
print('No message')
else
print(test.Subject)
print(test.Count)
i = test.Count
i = i-1
for v = 0, i, 1 do
--print(test.Count)
print('key: '..tostring(test:Keys(v))..' Value: '..tostring(test:Values(v)))
end
end
end
I am calling myest() as part of the timer, yet it seems to only get executed once. Any idea what I am doing wrong
Rob H
September 30th, 2006, 04:34 AM
Actually you are only calling it when you create the timer itself - you need a function in there e.g.
meediotimer = gir.CreateTimer("", function() mytest(meedio) end,"", true, true)
nurowolf
October 1st, 2006, 03:23 AM
OK. I changed it to what was suggested above and now I get the following error.
Timer (pcall): [string "MeedioClient.gml:\New\Connect to Meedio"]:47: attempt to call method `GetNextMessage' (a nil value)
It calls the function mytest(meedio) ok on the first pass through, bit on the second pass through - it seems to have forgotten what the meedio object is and what its methods are.
Any advice on how to deal with this????
Rob H
October 1st, 2006, 03:43 AM
Well, for one thing, you have two mytest functions. Not sure which one will be called. The first one will be using the global meedio variable and the second one will be using the parameter. I'd suggest just having the one function that takes a parameter and putting it before the timer creation code
You may need to change the code that arms the timer to the following
local myMeedio = meedio
meediotimer = gir.CreateTimer("", function() mytest(myMeedio) end,"", true, true)
meediotimer:Arm(100)
nurowolf
October 1st, 2006, 04:15 AM
So here is my updated code - mith only 1 mytest() function this time.
function mytest(myMeedio)
test = myMeedio:GetNextMessage()
if test==nil then
print('No message')
else
print(test.Subject)
print(test.Count)
i = test.Count
i = i-1
for v = 0, i, 1 do
--print(test.Count)
print('key: '..tostring(test:Keys(v))..' Value: '..tostring(test:Values(v)))
end
end
end
Result = False
meedio = luacom.GetObject("MeedioClient.MeedioPluginClient")
if meedio then
print('Meedio already connect')
else
meedio = luacom.CreateObject("MeedioClient.MeedioPluginClient")
--assert(meedio)
myhandle,myerr = win.FindWindow('TApplication','Girder 4.0')
print(myhandle)
Result = meedio:Connect('localhost', 7500, 'password', myhandle, 1040 )
if not Result then
print('no connection')
else
print('connection made')
local myMeedio = meedio
meedio:AddSubjectMask('*')
meediotimer = gir.CreateTimer("", function() mytest(myMeedio) end ,"",true, true)
meediotimer:Arm(100)
end
end
And this is the error I get.
Timer (pcall): [string "MeedioClient.gml:\New\Connect to Meedio"]:4: attempt to call method `GetNextMessage' (a nil value)
nurowolf
October 1st, 2006, 04:18 AM
If I change the timer code to the following;
local myMeedio = meedio
meedio:AddSubjectMask('*')
meediotimer = gir.CreateTimer(function() mytest(myMeedio) end,"" ,"",true, true)
meediotimer:Arm(100)
I don't get an error, but the mytest(myMeedio) function is only called one time.
I thought from the doco I could have put the function call as either a TRIGGER or an ARM argument.
Rob H
October 1st, 2006, 04:27 AM
And if it's called in the trigger then you don't get the error? That's very weird.
Sounds as though something is modifying the meedio variable in the meantime. Do you have any other GML code that's changing the global meedio variable?
Try adding
local meedio
at the very start of that script - that should isolate it from any other code.
nurowolf
October 1st, 2006, 04:46 AM
i dont think so. i will change the variable name to make sure.
nurowolf
October 1st, 2006, 04:56 AM
So I changed the variable name from meedio to meedio xyz123.
Now I am sure that that variable name is never used anywhere. I also moved the function call back to the Trigger parameter and I get;
Timer (pcall): [string "MeedioClient.gml:\New\Connect to Meedio"]:4: attempt to call method `GetNextMessage' (a nil value)
It is like the Meedioxyz123 is not available on the thread that is being executed.
Rob H
October 1st, 2006, 05:04 AM
If you call myTest(meedio) immediately before the call to createtimer it works?
nurowolf
October 1st, 2006, 05:11 AM
yep - it sure does.
It works when
a) - I call mytest() outside of the gir.CreateTimer object
b) - I call mytest() inside the gir.CreateTimer object as the Arm argument
It does not work when
a) - I call mytest() inside the gir.CreateTimer object as the trigger argument.
Problem with the above is that in the working examples - the code only gets called once.
Rob H
October 1st, 2006, 07:20 AM
I'm afraid I'm a bit stumped.
Can you call any other methods of the meedio object? e.g. Flush
nurowolf
October 1st, 2006, 08:14 AM
I actually got around it.
What I did was break my code into several Scripts and attach events.
SO I moved the mytest() function to a new script and used the following to set of the timer;
meediotimer = gir.CreateTimer(nil, [[gir.TriggerEvent('MeedioMsgLoop',18)]],"",true, false)
meediotimer:Arm(400)
And now it works fine. Not a great solution for making this a deployable piece of code, but it works and I get a message loop and I can send messages to Meedio no problem.
Rob H
October 1st, 2006, 09:30 AM
Ah, well done.
Presumably the trigger function is being called on a different thread, so COM won't work since CoInitialise won't have been called for that thread.
You should be able to put it all into one script by using gir.RegisterEventHandler
nurowolf
October 2nd, 2006, 05:58 AM
I will revisit this once I have it all working.
Being forced to break it into smaller scripts with events actually makes the debugging easier.
Thanks for the help.
blubberhoofd
October 2nd, 2006, 08:21 AM
Hi Nurowolf,
can you give an example of a message that you send to Meedio, something like screen refresh (as in refreshing a library that you're viewing with meedio) would be great ;)
nurowolf
October 2nd, 2006, 07:16 PM
Hi Blubber,
I have actually written a very small GENERAL Plugin for Meedio that listen for very specific messages.
So the messages I send to Meedio are;
NR.Start (Initiates the handshaking)
NR.NextAlbum (Retrieves the next Album)
NR.PrevAlbum (Retrieves the previous Album)
NR.AlbumPlay (Plays the album name that is in the message keys)
From Meedio I send
NR.Started (Confirms Handshake)
NR.Album (Holds details of Album Name, Artist, And Album Cover Image)
The General Plugin called NRJukeBox (all I could come up with) does the library work within the module. Based upon the message received it knows what to do. Makes it much easier than having to get really complicated message structures working in LUACOM. I expect that i will add more messages soon, but will see how I go.
Currently I have it working except for the passing of the image file to NetRemote from Girder.
What I need to do before this can be released is
a) Resolve the issues I have idetified in this thread (that is have all the girder code as a single module and not use Event Triggers.
b) Fix the Image Problem
c) Speed up the Meedio Plugin initiation (need to look at threading as it takes a while at the moment)
Between the Girder camp here and their help with LUACom and the MeediOS guys, this hasn't been to difficult.
Powered by vBulletin® Version 4.1.8 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.