annotate lua/luadyncall/src/dynport.lua @ 37:8c8f848131c6

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