lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]



> -----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
> 
>