Prev: Water plant design | Design Build | Water plant construction
Next: Two programs with same logic
From: BGB / cr88192 on 24 Dec 2009 13:54 "Colin Paul Gloster" <Colin_Paul_Gloster(a)ACM.org> wrote in message news:alpine.LNX.2.00.0912241319270.31236(a)Bluewhite64.example.net... > On Mon, 21 Dec 2009, BGB / cr88192 posted: > > |-------------------------------------------------------------------------| > |"[..] > | > | > | > |my reasons for using C are varried, although, part of it may be that > [..]| > |[..], and also I use > | > |some amount of "reflection", which does not work so well with C++ > (mostly| > |giving the non-standardized name mangling and compiler behaviors, ...). > | > | > | > |[..]" > | > |-------------------------------------------------------------------------| > > Hi! > > How and why do you use relection in C? > how: piles and piles of code implementing it (this is hardly a small piece of code); some use of API's like ToolHlp, DbgHlp, ... (these are provided by Windows to help implement debuggers). (much of this has Linux analogues, many via libdl and extensions, ..., but keeping the Linux port alive and well has been, well, lacking...). customized in-memory linking code, a custom DLL loader and an x86 interpreter; a database to manage metadata (shared variable, function, and type declarations, ...); an dynamic C cimpiler (more needed for eval and dynamic loading, not so much for reflection, but it does have uses getting data loaded into the DB); .... of note, machine code, and plain compiled C, does not, in itself, contain sufficient information to allow for reflection, rather, it requires a whole lot of "support machinery" which serves in part to gather and build this information, and a lot of dynamic code generation to actually be able to make use of it for anything. for example, one can realize after writing a C compiler that, for its internal operation, it generates piles of useful information, but nearly all of this is lost with the generated code. a database was then used to capture some of this data, so that data can be mined from any code or headers which pass through this compiler (going further, I eventually ended up adding a "dummy mode" to the compiler upper end, which basically mines info but does not bother generating any code). the info in the database is then used in conjunction with information in the run-time linker, mostly to allow accessing variables, dynamically calling functions, ... (basically, I can do something sort of like the LISP-style 'apply' with C function pointers, including with dynamically-typed arguments, given limited static<->dynamic auto-marshalling exists). a downside: I am more recently using MSVC for building, and this strips symbols/... from produced PE/COFF images, which hurts the ability of my dynamic code to access any "non-exported" statically-compiled+linked code (say, in DLL's), however, in practice this has not hurt too badly (some of this could be helped if info from the PDB files were used, and it were required that code always be built with debugging options, but given in MSVC this breaks optimization, I have not been willing to generally accept this cost). (when I was building with GCC, it left symbol info in the produced PE/COFF images, and I would mine this info as well). another downside: dynamic C compilation seems nicer in theory, as it can be noted that C does not compiler "instantly" (nor is my compiler entirely bug-free), which someone hurts my motivation to compiler the C code at run-time (although, dependency tracking and object-file caching does help here, since it can limit re-compiles mostly to dependency-check failures...). the result is that I end up doing a lot of dynamically generated code in ASM, which is not a good option either, and I currently lack any good "middle of the road" language (although, I had considered a wide range of options, including allowing a C variant which was relaxed some and able to "see" all of the declarations in the metadata DB without need for explicit declaration or import, hence "header-free", ...). similarly, the effort has not been extended to cover C++ for various reasons (for example, MSVC and GCC have different ABIs, and my framework yet still another ABI, ...). (now consider that there is a half-assed Java implementation in the mix, ....). and, further: although it is possible to patch functions at runtime, this is ill-advised with any statically compiled code (EXE and DLL images), since there is little to say that the patch will actually effect said static code, or that this patching will not instead crash the statically-compiled app. there are also some edge cases where this patch will not be properly updated (say if function pointers exist to the pre-patch version). a workaround exists, however: it requires being explicit about patchable functions (kind of defeats the purpose of patching); it requires compiling patchable code via my compiler; the same effect is easily enough done in static land via specialized use of function pointers (or via COM interfaces). why: all this is a harder issue... sadly, I have since noted that there are many cheaper and simpler ways to do nearly everything I have done, giving me doubts at times as to whether this all was a worthwhile effort... after all, one can hard-code nearly any of this, or address many of these cases though special-purpose functions or by doing (generally terrible) things with pointers, ... I am left also thinking that maybe had all this actually been "designed" (rather than hacked and extended in a piecewise manner), a much simpler piece of technology could have addressed all these uses, ... in some ways, it is sort of like .NET without the bytecode. (and, hence, no direct binary compatibility between Win32/Linux x86/Win64/Linux x86-64... or at least apart from using the interpreter...). any what if one wants interpretation or bytecode, well then I have an interpreter, which in turn does x86 (actually, this uses a POSIX-derived set of APIs, and supports multiple processes, sockets, shared memory, ..., but uses PE/COFF rather than ELF or similar...). and, in turn, the world visible from the interpreter is not too much different from that I tried to escape, as, once again, it is largely without reflection or high-level abilities (although, these could be added as APIs...). but, nearly all of my stuff does not work cleanly between disjoint address spaces, which is, lame... (although, eval would not be difficult to pull off, since it would just require sending the object over to the interpreter and linking it there). instead I am left considering the possibility of something like DCOM, which is something I initially terribly wanted to avoid... > With kind regards, > Colin Paul Gloster
From: Ed Prochak on 29 Dec 2009 13:10
On Dec 19, 2:56 pm, William Ahern <will...(a)wilbur.25thandClement.com> wrote: > Thad Smith <ThadSm...(a)acm.org> wrote: > > jacob navia wrote: > > >http://cacm.acm.org/magazines/2009/5/24646-api-design-matters/fulltext > > > > Communications of the ACM rarely bring something practical. > > > This is a good exception. > > > > It is a good article about API design, and the problems of bad APIs. > > Agreed. I plan to distribute the link to others at work. It makes > > A good API emerges from iteration. You really can't know how to make a new > API work for you until you've used it in various situations. Tweak, use, > tweak use. Sometimes after two or three iterations you have a really solid > design, sometimes you need more. A couple of the authors suggestions in that > paper reflect this dilemmea, with the vain suggestions about documentation > and separating the caller from implementor. > > Iteration is extremely hard to accomplish in a commercial environment with > other engineers because re-writing code is usually frowned upon, especially > once others have begun using the interface. (Thus if you separate caller > from implementor you'll never get the opportunity to change the API; and > it's foolish to think the first try will be even remotely optimal.) The rule I try to follow is based somewhat on hardware development.: throw away the prototype! IOW, your first iteration is seldom optimal. As long as the project manager understands that, you are okay. Ed |