首先说明一下,这个应该是与 luajit 的 namespaces 设计有关,似乎不是 openresty 的问题,但鉴于我只在使用 openresty 的时候才会用到 luajit,所以发到这里看看哪位有什么好办法。
nginx.conf
server
{
listen 80;
server_name test;
error_log /data/logs/test.error.log;
location /a
{
default_type 'text/plain';
content_by_lua '
local a = require("a")
ngx.say(a.ip2long("8.8.8.8"))
';
}
location /b
{
default_type 'text/plain';
content_by_lua '
local b = require("b")
ngx.say(b.ip2long("8.8.8.8"))
';
}
}
a.lua 与 b.lua 内容完全一样,是之前agentzh写的的作为ffi例子的php.utils
local ffi = require "ffi"
module(...)
ffi.cdef[[
struct in_addr {
uint32_t s_addr;
};
int inet_aton(const char *cp, struct in_addr *inp);
uint32_t ntohl(uint32_t netlong);
char *inet_ntoa(struct in_addr in);
uint32_t htonl(uint32_t hostlong);
]]
function ip2long(ip)
local inp = ffi.new("struct in_addr[1]")
if ffi.C.inet_aton(ip, inp) ~= 0 then
return ffi.C.ntohl(inp[0].s_addr)
end
return nil
end
function long2ip(long)
if type(long) ~= "number" then
return nil
end
local addr = ffi.new("struct in_addr")
addr.s_addr = ffi.C.htonl(long)
return ffi.string(ffi.C.inet_ntoa(addr))
end
实际请求时,结果却不同
[root@xx conf]# curl "
http://test/a"
134744072
[root@xx conf]# curl "
http://test/b"
<html>
<head><title>500 Internal Server Error</title></head>
<body bgcolor="white">
<center><h1>500 Internal Server Error</h1></center>
<hr><center>nginx</center>
</body>
</html>
同时 error.log 里出现如下错误
2012/12/04 11:54:49 [error] 10709#0: *17 lua entry thread aborted: runtime error: /usr/local/openresty/nginx/conf/luapkg/b.lua:15: attempt to redefine 'in_addr'
stack traceback:
coroutine 0:
[C]: in function 'require'
[string "content_by_lua"]:2: in function <[string "content_by_lua"]:1>, client: 127.0.0.1, server: test, request: "GET /b HTTP/1.1", host: "test"
看错误,是 b.lua 里用 cdef 定义 in_addr 时出现重新定义,也就是说在 a.lua 里定义过的 in_addr,即使写法上是在一个 lua module 里,但实际是全局定义的,似乎与 luajit 文档中
http://luajit.org/ext_ffi_semantics.html 的 C Library Namespaces 一段描述有关。
假如在大量使用 ffi 的场合,这种重复定义似乎很难避免,哪位有什么好办法?
Lance