On Sun, Mar 18, 2012 at 09:52:12PM -0700, Gregory Szorc wrote:> The automatic generation of the Python ctypes interfaces using the Clang > Python bindings is pretty friggin cool!A nice side effect is that everything is added to the interface. So it is easy to add a small proxy over the lib that shows which parts of the llvm-c API that is exercised by the tests. (have that in my bindings)> > * 0004-Add-LLVMPrintModule-to-llvm-c.patch > > Adds a new LLVMPrintModule function which is similar to > > LLVMDumpModule but dumps to a string instead of stdout. > > > > * 0005-Add-LLVMCreateMemoryBufferFromData-to-llvm-c.patch > > Adds LLVMCreateMemoryBufferFromData function. > > These are desperately needed by the C API. Can you please submit them?Will do!> FWIW, all my work is at > https://github.com/indygreg/llvm/tree/python_bindings/bindings/python.Excellent! I'll try to see if I can adapt my bindings to your to fill in the gaps. There do indeed seem to be much overlap in our bindings. But there are a few things where the design differs. If we should try to combine our work I guess it would be a good idea to discuss these differences, to make sure we work towards a common goal. I think the main differences between our bindings are: * Auto generated vs manual ctypes declarations. From your comment above I assume you would prefer auto generated too. * Types inheriting from c_void_p vs having a ptr attribute. My bindings has for example Module (indirectly) inheriting from c_void_p, that way there is no "from_param" methods needed, and no extra attribute of the actual pointer. I'm not sure this is better. I might have done with separate pointer as you have if I started from scratch today. * Use of constructor vs "new" static methods. When using the bindings one never initializes the class manually. Instead a "factory" method is used: mymod = Module.from_file(...) mymod = Module.from_data(...) mymod = Module.new("foo") ity = Type.int(32) instead of mymod = Module(file=...) mymod = Module(data=...) mymod = Module(name="foo") ity = IntType(32) I prefer this in, especially in the cases where there are many different ways to construct an item. Also many objects are not really created standalone. e.g a function is added: f = Module.add_function(FTy, "foo") and the Function constructor is never used. That way having the policy "never use constructor" to create objects makes it consistent. Also this makes it consistent with the old defuct llvm-py bindings. (partially this also is a consequence of the fact that my bindings inherits from c_void_p making it a bit messier) * Directory layout Just minor thing. My bindings have python/bindings/lib/llvm /tests /tools I do like having the tests outside the dir.> Parts of Core.h still need love (especially the Value system). I'm doing > some dynamic type creation at run-time using the Value hierarchy. > Somewhat scary stuff, but it does seem to work. I really need a > LLVMGetValueID() API to fetch llvm::Value::getValueID() to enable more > efficient value casting.I'm doing the very same thing in my bindings, and yes it is a bit inefficient, but seems to work fine and should work fine as long as classes are not moved in the hierarchy. I use the same hierarchy at python level. And at python level recursivly drills down into the correct subclass by doing LLVMIsA* for the possible (direct) subclasses.> From some discussion on #llvm, I think people > are receptive to this. The main concern would be that the C API would be > tied to a specific version of the shared library because the value ID > enumeration aren't guaranteed for all of time. But, that contract is > already broken, so I don't think it's a big deal: just something that > needs to be documented. Of course, Python is a dynamic language, so if > there were a C API that exposed the llvm::Value class hierarchy, we > could always have Python dynamically create types at run-time :)I guess we could have a separate valueid enum and a mapping between llvm-c<->c++ valueid. IIRC the clang python bindings does that for for something. That way there wont be any breakage if the c++ side is changed. anders
On Mon, Mar 19, 2012 at 10:44 AM, Anders Waldenborg <anders at 0x63.nu> wrote:> > * Auto generated vs manual ctypes declarations. >This is purely a cosmetic difference, as we both take the same approach of registering functions on a global/shared ctypes library instance. I think automatic is the way to go (just as long as the automatically generated code is easy to diff when they are regenerated). * Use of constructor vs "new" static methods.> > When using the bindings one never initializes the class manually. > Instead a "factory" method is used: > > mymod = Module.from_file(...) > mymod = Module.from_data(...) > mymod = Module.new("foo") > ity = Type.int(32) > > instead of > > mymod = Module(file=...) > mymod = Module(data=...) > mymod = Module(name="foo") > ity = IntType(32) >Yeah, Module is an example where the number of named arguments is pretty overwhelming. I was probably going to create static methods for Module creation. Whether I was going to leave the named arguments on the constructor is an open issue. I don't think it matters too much.> Also this makes it consistent with the old defuct llvm-py bindings. >I'm not too concerned about this consistency. llvm-py began many years ago. Assumptions may be different now. I think we should do what makes sense today. If that is the same great. If not, oh well.> (partially this also is a consequence of the fact that my bindings > inherits from c_void_p making it a bit messier) >Yup :) Since I started without this inheritance restriction, I was able to go with what I consider a more "Pythonic" approach: initializers.> My bindings have python/bindings/lib/llvm > /tests > /tools > > I do like having the tests outside the dir. >I have no major opinion on this. In related news, I see you have received commit access, Anders. Congratulations! We just need to figure out this review/module owner situation... Gregory -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20120320/04c8efbe/attachment.html>
On Tue, Mar 20, 2012 at 10:07:14PM -0700, Gregory Szorc wrote:> automatic is the way to go (just as long as the automatically generated > code is easy to diff when they are regenerated).Yes it should be easy to diff. My generated code is in the same order as in the llvm-c/*.h files.> Yeah, Module is an example where the number of named arguments is pretty > overwhelming. I was probably going to create static methods for Module > creation. Whether I was going to leave the named arguments on the > constructor is an open issue. I don't think it matters too much.I don't think it matters that much either. BUT I think consistency matters, so it should be decided upon before the API grows. Just having static methods resonates well with the "only one" part of "There should be one - and preferably only one - obvious way to do it.", the question is how obvious it is.. (I think that the internals of the bindings can be simpler if all initializers just takes a pointer. But if the choice is between cleaner API or cleaner internals the choice is easy.)> I'm not too concerned about this consistency. llvm-py began many years ago. > Assumptions may be different now. I think we should do what makes sense > today. If that is the same great. If not, oh well.I totally agree.> > I do like having the tests outside the dir. > > > > I have no major opinion on this.Me neither. It was mostly an obvervation. As long as the tests doesn't do relative imports so they easily can be run againts another version. There was another (minor) difference. All testcases in my bindings were written as functions (i.e no containing UnitTest class), as nosetests picks them up just fine. I'd don't mind changing them to UnitTest when/if I port them over.> In related news, I see you have received commit access, Anders. > Congratulations!Yay! I even managed to commit some stuff!> We just need to figure out this review/module owner > situation...Yeah. I'm not even sure where we stand today. It is quite messy to keep track of everything with the official stuff in the svn repo, your pythonbindings git repo and my local stuff. I'm not sure what to do. I guess trying to make sure there is as little code floating around outside of the official svn repo is good goal. anders