[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: RE: Need some help to use TFUNCTION
- From: Thijs Schreijer <thijs@...>
- Date: Tue, 9 Jun 2015 14:18:21 +0000
> -----Original Message-----
> From: lua-l-bounces@lists.lua.org [mailto:lua-l-bounces@lists.lua.org] On
> Behalf Of Laurent FAILLIE
> Sent: zondag 7 juni 2015 14:55
> To: Lua mailing list
> Subject: Re: Need some help to use TFUNCTION
>
> So here I am : the full source code can be found
> https://github.com/destroyedlolo/Selene/blob/master/src/MQTT.c
>
>
> 1/ Environment creation :
>
>
> struct enhanced_client {
> MQTTClient client;
> lua_State *L;
> struct _topic *subscriptions;
> };
>
> ...
>
>
> /* Creating Lua data */
> eclient = (struct enhanced_client *)lua_newuserdata(L, sizeof(struct
> enhanced_client));
> luaL_getmetatable(L, "SelMQTT");
> lua_setmetatable(L, -2);
> eclient->subscriptions = NULL;
> eclient->L = luaL_newstate();
> luaL_openlibs(eclient->L);
> ...
>
>
> 2/ registering the callback
>
> ...
>
> lua_pushstring(L, "func"); /* Argument cames from a table */
> lua_gettable(L, -2);
> if( lua_type(L, -1) != LUA_TFUNCTION ){
> lua_pop(L, 1); /* Pop the result */
> lua_pushnil(L);
> lua_pushstring(L, "Subscribe() : topics needs associated
> function");
> return 2;
> }
> lua_xmove( L, eclient->L, 1 ); /* Move the function to the
> callback's stack */
> func = luaL_ref(eclient->L,LUA_REGISTRYINDEX); /* Reference the
> function in callbacks' context */
> ...
>
>
> 3/ calling the callback function
>
>
> int msgarrived(void *actx, char *topic, int tlen, MQTTClient_message *msg){
> /* handle message arrival and call associated function.
> * NOTE : up to now, only textual topics & messages are
> * correctly handled (lengths are simply ignored)
> */
> struct enhanced_client *ctx = actx; /* To avoid numerous cast */
> struct _topic *tp;
>
> for(tp = ctx->subscriptions; tp; tp = tp->next){ /* Looks for the
> corresponding function */
> if(!strcmp(tp->topic, topic)){ /* AF : wildcard to be done */
> lua_rawgeti( ctx->L, LUA_REGISTRYINDEX, tp->func); /*
> retrieves the function */
> lua_pushstring( ctx->L, topic);
> lua_pushstring( ctx->L, msg->payload);
> lua_pcall( ctx->L, 2, 0, 0); /* Call Lua callback function */
> }
> }
>
> MQTTClient_freeMessage(&msg);
> MQTTClient_free(topic);
> return 1;
> }
>
> 4/ Finally, a Lua example :
> https://github.com/destroyedlolo/Selene/blob/master/Selenites/MQTT.sel
>
> print '\nTesting broker connection'
> print '--------------------------'
>
> -- Callbacks
> function handle_tata( topic, msg )
> print("Lua received t:'" .. topic .."' m:'".. msg .. "'\n");
> end
>
>
> function handle_toto( topic, msg )
> print("Lua received t:'" .. topic .."' m:'".. msg .. "'\n");
> end
>
> -- Connection, subscription and finally waiting for messages
> Brk, err = SelMQTT.connect( "tcp://localhost:1883", { reliable=false } )
> if not Brk then
> print( err )
> return
> end
>
> _, err = Brk:subscribe( { { topic = "/tata/#", func=handle_tata,
> qos=SelMQTT.QoSConst("QoS0") }, { topic = "/toto",func=handle_toto } } )
> if err then
> print( err )
> return
> end
>
> print "Hit 'enter' key to exit"
> io.stdin:read'*l' -- wait for enter
>
> And it seems it's working pretty well.
> If I enter in another shell :
> ---
> torchwood ~ # mosquitto_pub -h torchwood.local -t '/toto' -m 'Coucou'
> ---
>
> I got
> ---
> torchwood Selene # Selenites/MQTT.sel
> Testing broker connection
> --------------------------
> Hit 'enter' key to exit
> Lua received t:'/toto' m:'Coucou'
> ---
>
> Can someone having a look and tell me if I made a mistake ?
After a quick glance; it's just single state code. If you mix (preemptive os) threads in this state, it will fail sooner or later.
From what I understand; you have a C program, which embeds Lua, and the Paho library. The Paho library creates a separate background OS thread for the async handling of incoming data. So you have two OS threads that might access the Lua states simultaneously, which requires synchronisation.
>
> Now, I'll have to work data shared b/w threads :)
Yes you have to, see remark above...
If you create multiple States, and sync between them using mechanism X, you might as well directly use mechanism X from the Paho callbacks and use a single Lua state. No?
Thijs
>
> Thanks for all.
>
> Laurent
>
> ---
> The misspelling master is on the Web.
> _________ 100 % Dictionnary Free !
> / /(
> / Dico / / Pleins d'autres fautes sur
> /________ / /
> (########( / http://destroyedlolo.info
> Quoi, des fautes d'orthographe! Pas possible ;-D.
>
>
> Le Dimanche 7 juin 2015 12h01, Laurent FAILLIE <l_faillie@yahoo.com> a écrit
> :
>
> Le Dimanche 7 juin 2015 11h15, Thijs Schreijer <thijs@thijsschreijer.nl> a
> écrit :
>
>
> > The naming of some elements in the C api is a bit misleading. Personally I
> wish that all wording with "thread"
> > would be changed to "coroutine", and the lua_State would be renamed to
> "executionstack" or something
> > more appropriate.
>
> Yes, I totally second that, it's a bit confusing, especially because Lua's
> thread aren't preemptive.
>
> Thanks for the links, I'll check them if I can't succeed with my current
> thinking;
>
> > I'm not familiar with Paho, but how is is used? Is the main loop on the C
> side and are messages passed to Lua
> > to be handled with scripting, or is the main loop on the Lua side? Does
> Paho create the new os threads?
> > Do you have control over that behaviour? Does it also generate new Lua
> states?
>
> Paho ( https://eclipse.org/paho/ ) is a messaging library implementing MQTT
> protocol, mostly associated with IoT stuffs.
> It supports several implementations : Java, C, C++ and even a native Lua
> library which is not finished up to now.
> I'm using the C implementation, which has nothing to do with Lua at all.
>
> My project is the following :
>
> - I have several daemons running in my basement server to do "smart
> housing", and monitoring several figures of my home : electricity
> consumption and production, temperature in rooms, pool, health of my
> Internet connection, and so on and so forth ...
> https://github.com/destroyedlolo/TeleInfod and
> https://github.com/destroyedlolo/Marcel are some example of such daemon.
> - Daemons and my supervision tool are exchanging data using MQTT messaging :
> the big advantage is it runs in pub/sub model so I can add / remove / modify
> any part of my network without touching the remaining.
>
> Now, I'm working now on the "home dashboard" part which will plug-in on this
> network and will display some valuables informations on a screen on my
> living room.
>
> - The main work is done in C and takes in charge all the dirty / low level
> work. This technical layer is https://github.com/destroyedlolo/Selene
> - Selene embeds Lua as end user scripting language, which will be used to
> build the final dashboard (has to be done). And to respond to your question,
> yes, messages are handled in C then passed to Lua part for end user oriented
> processing.
>
> The main advantage is a clear separation b/w the technical layers and the
> end user interface itself.
>
> - Laurent
>
>