On Tue, May 29, 2012 at 8:25 PM, Mike Pall <mike-1205@xxxxxxxxxx> wrote: > Cosmin Apreutesei wrote: >> On Mon, May 28, 2012 at 9:59 PM, Mike Pall <mike-1205@xxxxxxxxxx> wrote: >> > Anyway, the questions you're asking sound like you're going for >> > some awfully complicated abstractions, which is rarely a good >> > idea. If this is still your WIN32 bindings, then I'd be very >> > surprised if all of that is truly necessary or even helpful. :-) >> >> Funny how people react on the second wish-like feedback they get from >> the same user in a short period of time - now you're a noob and must >> be doing something wrong :) > > I'm sorry if I have offended you. That was not my intention. It's > just that the last few questions you've been asking have left me > puzzled. No offence really. I appreciate the explanation - it encouraged me to write this long post. > > I still don't know why one would want to use ctypes as table keys > or why one would want to traverse through tables (with pairs()?!) > and compare cdata values for equality. Really, I don't. > > Very often when I get 'strange' feature requests, it later turns > out that someone tried a couple things and ended up with a > complicated solution for a simple problem. I see only the end of > the thought process and then have to turn down the feature request. > Of course people are not going to be overly happy with that ... > > However, if the requestor would tell us: > > "I'm trying to do A with B, which didn't work. Now I've come up > with complicated solution C, which needs feature D. Am I still > on the right track?" > > ... then several people (not just me) could voice in with > suggestions on doing it the "right way" (if there is one) or > reformulate the problem. I see your point. Thanks for that. I need to put in more effort in these emails (btw the reason I'm reluctant to add the background story is that it usually refocuses the discussion around my particular problem which I was trying to solve losing the issue in the process -- so I'll add the "issue" and the "story" separately see how that goes). 1) issue It's a useful Lua invariant that == never breaks because it makes possible for a function to do a linear search for a value in an arbitrary table without breaking. It also allows a function to check that an argument or a table key has a specific non-cdata value when that argument/key can also be a cdata. 1) story The function bellow attempts to find the name of a constant in the winapi namespace given a prefix and a value. I cached a few ctypes in that namespace cuz I heard it's a good idea (faster than parsing). That's when it broke and had to add those additional checks. --search the name of a constant in the winapi namespace (linear search!) function findname(prefix, value) for k,v in pairs(_M) do if k:starts(prefix) and type(v) ~= 'cdata' and type(value) ~= 'cdata' and v == value then return k end end return tonumber(value) ~= nil and '%x' % value or value end This was already solved so I won't be beating on it (do ask for more examples if you want). 2) issue It would be useful if cdata pointers would anchor their target if it's a struct or array. In Lua an unreachable object can be safely collected only because by definition it cannot affect any other object. Why not extend this useful semantic to ffi pointers? Ok, some APIs get you pointers to data that isn't yours, but a lot more APIs work only on your own buffers. For those, it would mostly eliminate the possibility of dangling pointers which is a big opportunity for making programs safer. Plus this property is so much taken for granted in Lua that it's easy to forget and write innocently looking code like SNDMSG(hwnd, BCM_GETIDEALSIZE, 0, ffi.cast('SIZE*', ffi.new('SIZE', size)))). 2) story In winapi there's tons of structs with short* buffers. In fbclient (firebird's client library) there's even structs with pointers to structs with pointers to arrays, all that you allocated yourself. I have two options: a) cram all related structs and buffers in tables and carry those around or b) use weak tables which gets me transparent anchoring (weak tables are underrated :)). I use both methods. For instance, I made a struct wrapper that adds virtual fields to structs via ffi.metatype(). You can then opt to read/write to the structs through these virtual fields or through the original fields at no cost. Using the virtual fields though gives you automatic anchoring of cdata (implemented with weak tables), get/set individual bits in bitfields, setting of struct's bitmask each time a field is assigned a value, string to wcs conversion and back, and more. The only problem I have with the weak table approach is that I don't have enough ffi introspection to distinguish between mutable and immutable cdata, so I needlessly anchor pointers too (small issue though). 3) issue ffi introspection (this has been asked before and probably answered, but I'll give my reasons), especially struct fields (name & type). 3) story Automatic testing (eg. code generation for unit tests stubs). Debugging tools (eg. pretty-print a struct). Ok that's my top 5% :) > >> My code is online so you can verify your intuition about my >> complicated abstractions :) > > Sadly, I don't have the time to hunt down every piece of Lua code > and do a full code critique. I generally try to give hints on best > practices, if I see code snippets posted here. > >> My postings are to provide user feedback. I already feel very >> comfortable with the API as it, we're talking edges here. Also, I >> can't answer to the feasibility of implementing these things so I >> don't know which are a complete waste of your time and attention. >> >> So, what do you suggest I do with my wishes? Tell'em or shove'em? > > No no, please keep posting your feature requests! But it would > definitely help to give them some context or motivation. Thank you! That's encouraging, thanks. > > --Mike >