comparison lua/luadyncall/src/dynport.lua @ 0:0cfcc391201f

initial from svn dyncall-1745
author Daniel Adler
date Thu, 19 Mar 2015 22:26:28 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:0cfcc391201f
1 require "dynload"
2 require "dyncall"
3 require "path"
4
5 local function makewrapper(addr, signature)
6 return function(...) return dyncall(addr, signature, ...) end
7 end
8
9 loaded = { }
10
11 --- The dynport path is initialized by LDP_PATH environment.
12 -- @usage Defaults to dynport_syspath.
13 dynport_path = pathinit("LDP_PATH","?.dynport;/usr/local/share/dynport/?.dynport;/opt/local/share/dynport/?.dynport")
14
15 local function find(name)
16 return pathfind( dynport_path, name, io.open )
17 end
18
19 --[[
20 local LDP_PATH = "?.dynport;/usr/local/share/dynport/?.dynport;/opt/local/share/dynport/?.dynport"
21 local path = os.getenv("LDP_PATH") or LDP_PATH
22
23 local function find(name)
24 local replaced = path:gsub("?", name)
25 local f = nil
26 local hist = {}
27 for filename in replaced:gmatch("([^;]+)") do
28 f = io.open(filename)
29 if f then break else
30 table.insert(hist, "\tno file '")
31 table.insert(hist, filename)
32 table.insert(hist, "'\n")
33 end
34 end
35 if f then
36 return f
37 else
38 error("dynport '"..name.."' not found:\n"..table.concat(hist), 3)
39 end
40 end
41 ]]
42
43
44 --- Process dynport files.
45 -- Files will be opened and processed according to the dynport format.
46 -- Function wrappers and constants will be installed.
47 -- Structure/Union type information have not been implemented yet.
48 -- @param name dynport name to lookup.
49 -- @unit table to use for import.
50 -- @field _dynport_libs contains.
51 -- @return unit table with imports.
52
53 function dynport_NEW(portname, t)
54 local t = t or _G
55 local port = loaded[portname]
56 if port then return port end
57 local file, errmsg = searchpath(portname, path)
58 if not file then error(errmsg) end
59 end
60
61 function dynportImport(name, unit)
62
63 local file = find(name)
64
65 if not unit._dynport_libs then
66 unit._dynport_libs = { }
67 end
68
69 local cached = unit._dynport_libs[name]
70 if cached then return unit end
71
72 if not file then
73 error("dynport "..name.. " not found")
74 end
75
76 local iter = file:lines()
77
78 local libs = { }
79
80 function dolib()
81 local libnames = ""
82 for line in iter do
83 if line == "." then break end
84 libnames = line
85 end
86 libs[#libs+1] = dynload(libnames)
87 end
88
89 function dofun()
90 local index = 1
91 local unresolved = {}
92 for line in iter do
93
94 if line == "." then break end
95
96 local pos = line:find("[(]")
97 local symbol = line:sub(1, pos-1)
98 local stop = line:find("[;]", pos+1)
99 local signature = line:sub(pos+1,stop-1)
100
101 local addr = dynsym(libs[#libs], symbol)
102
103 if type(addr) == "userdata" then
104 rawset(unit, symbol, makewrapper(addr, signature) )
105 -- module[symbol] = makewrapper(addr, signature)
106 else
107 unresolved[#unresolved] = symbol
108 end
109
110 end
111
112 if #unresolved ~= 0 then
113 print("unresolved symbols:")
114 print(table.concat(unresolved,"\n"))
115 end
116 end
117
118 function doconst()
119 for line in iter do
120 if line == "." then break end
121 local pos = line:find("=")
122 local key = line:sub(1, pos-1)
123 local value = line:sub(pos+1)
124 -- module[key] = tonumber(value)
125 rawset( unit, key, tonumber(value) )
126 end
127 end
128
129 function dostruct()
130 for line in iter do
131 if line == "." then break end
132 end
133 end
134
135 function dounion()
136 for line in iter do
137 if line == "." then break end
138 end
139 end
140
141 for line in iter do
142 if line == "." then break
143 elseif line == ":lib" then dolib()
144 elseif line == ":fun" then dofun()
145 elseif line == ":const" then doconst()
146 elseif line == ":struct" then dostruct()
147 elseif line == ":union" then dounion()
148 end
149 end
150
151 unit._dynport_libs[name] = libs
152
153 return unit
154
155 end
156
157 --- Dynamic bind C library Interfaces.
158 -- @param name dynport name which will be searched by
159 function dynport(portname)
160 return dynportImport(portname, _G)
161 end
162
163