ports/108699: problem using user libraries with lua-5.0

Douglas Wells sysmaint at contek.com
Fri Feb 2 21:50:20 UTC 2007

>Number:         108699
>Category:       ports
>Synopsis:       problem using user libraries with lua-5.0
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-ports-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Feb 02 21:50:20 GMT 2007
>Originator:     Douglas Wells
>Release:        FreeBSD 6.2-RELEASE i386
Connection Technoloties
System: FreeBSD flame.contek.com 6.2-RELEASE FreeBSD 6.2-RELEASE #0: Fri Jan 12 16:08:49 EST 2007 root at flame.contek.com:/var/obj/other5/src.6.2/sys/FLAME i386

	I am using lua-5.0, updated today (lua-5.0.2_3). I have also
	today loaded lua-5.1, but I haven't gotten the problem to work
	yet. So, I am reporting the problem against 5.0, where I ran
	into it.

	I am new to lua and recently loaded lua-5.0 on my system.
	I noted that the standard language timing capabilities
	were fairly poor port (one second resolution) and attempted
	to write an extension to provide higher resolution.  I
	tried to follow the documentation (from manual.html), but
	found that I was unable to load my library (via loadlib).
	Chasing down the problem, I discovered that the default
	interpreter (lua-5.0) was not able to resolve the lua API
	functions while doing a dlopen.  If, however, I did explicit
	lookups of the functions, I could get my extension to

	Today I looked at the ports mail archives, and it appears
	to me that use of shared libraries might be fairly new.
	In any case, it seems to be that the lua interpreted is
	likely loading the shared library with the lua language
	APIs with the default loading parameters.  I might guess
	that it would be better if it were to use the RTLD_GLOBAL
	flag to dlopen. I think that would allow the loadlib
	function to resolve the lua APIs in my extension from the
	language shared library.

	I include a test program and my extension code (in C). If
	USE_DLOPEN is set to 0, the program fails; if it is set
	to 1, the program works (at least according to my definition
	of works):
	    Create the extension library:
		gcc -c -I  -I "/usr/local/include/lua50" c_funcs.c
		gcc -shared -o libcfuncs.so c_funcs.o	
	    Run the program:
		lua-5.0 uclock.lua
	    The program should print out an array of current times
	    with appx. microsecond precision. Instead it aborts with
	    error message:
		./libcfuncs.so: Undefined symbol "lua_pushnil"  open

	----------------- uclock.lua ---------------
	#! /usr/local/bin/lua-5.0

	print ("len of arg", table.getn (arg))
	limit = tonumber (arg [1] or '20')

	readuclock, err1, err2 = loadlib ("./libcfuncs.so", "readuclock")
	print (readuclock, err1, err2)
	assert (readuclock, "no libcfuncs.so / readuclock")

	io.write ("Time values:\n")
	tarr = {}
	for i = 1, limit, 1 do
	        tarr[i] = readuclock()

	prevval = 0
	for i = 1, limit, 1 do
	        local thisval = tarr[i]
	        if (thisval ~= prevval) then
	                diff = thisval - prevval
	                io.write (string.format ("%d: %f usecs\n", i, diff * 1e6))
	        prevval = thisval
	------------------ c_funcs.c -----------------------------

	#define USE_DLOPEN	0

	#include <stdio.h>
	#include <unistd.h>
	#include "lua.h"

	# include <dlfcn.h>

	# define LUALIBDIR	"/usr/local/lib/lua50"
	# define LUALIB		"liblua.so"

	typedef int (Lgettop_tp (lua_State *L));
	typedef void (Lpushnil_tp (lua_State *L));
	typedef void (Lpushnumber_tp (lua_State *L, lua_Number n));
	typedef void (Lpushstring_tp (lua_State *L, const char *s));

	void *
	get_lualibhndl (void)
	static	const char	*lualibpath = LUALIBDIR "/" LUALIB;
	static	void		*libhndl;

		if (libhndl == NULL)
			libhndl = dlopen (lualibpath, RTLD_LAZY);
			if (libhndl == NULL)
				fprintf (stderr, "Loading %s\n", lualibpath);

		return libhndl;

	return_error (lua_State *L, const char *msg)
		void		*libhndl = get_lualibhndl ();
		Lpushnil_tp	*pushnilp = NULL;
		Lpushstring_tp	*pushstrp = NULL;

		if (libhndl == NULL)
			fprintf (stderr, "%s\n", msg);
			return 0;

		pushnilp = dlsym (libhndl, "lua_pushnil");
		if (pushnilp == NULL)
			fprintf (stderr, "%s\n", msg);
			return 0;
		pushstrp = dlsym (libhndl, "lua_pushstring");
		if (pushstrp == NULL)
			fprintf (stderr, "%s\n", msg);
			return 0;
		pushstrp (L, msg);
		pushnilp (L);
		lua_pushnil (L);
		lua_pushstring (L, msg);

		return 2;

	readuclock (lua_State *L)
		void		*libhndl = get_lualibhndl ();
		Lgettop_tp	*gettopp = NULL;
		Lpushnumber_tp	*pushnump = NULL;
		int	numargs;
		int	numargs = lua_gettop (L);
		double	counter;
		struct timeval	tv;

		if (libhndl == NULL)
			return return_error (L, "no library");
		gettopp = dlsym (libhndl, "lua_gettop");
		if (gettopp == NULL)
			return return_error (L, "Locating lua_gettop");
		numargs = gettopp (L);
	/* fprintf (stderr, "readuclock called\n"); */
		gettimeofday (&tv);
		counter = tv.tv_sec + (tv.tv_usec / 1e6);

		pushnump = dlsym (libhndl, "lua_pushnumber");
		if (pushnump == NULL)
		if (gettopp == NULL)
			return return_error (L, "Locating lua_pushnumber");
	/* fprintf (stderr, "readuclock => %f\n", counter); */
		pushnump (L, counter);
		lua_pushnumber (L, counter);

		return 1;

	(Untested): Perhaps or in RTLD_GLOBAL in the call to dlopen in loadlib?

More information about the freebsd-ports-bugs mailing list