Replies: 13 comments 29 replies
-
@encukou I have a number of issues with the Python C API and would be happy to add any of them to the document if you feel that it is appropriate. Here is a brief run down of the main issues that I have encountered. If you see an issue that make sense to push to the google doc, just follow up on this discussion and I will try to elaborate. (I have posted these in the past to the Python dev list, but unfortunately my employer refuses to sign the Python contribution list and thus I simply can't fit them myself.)
As you can see this makes an O(1) lookup for language binding slots. If there were a slot in the class with an offset (usually negative to reference from them end I would not need such code.
Also please see it in action... jpype/native/common/jp_classhints.cpp Line 155 in f38a066
jpype/native/python/pyjp_class.cpp Line 134 in f38a066 I likely have another 3 more issues after this, but I have to head to my work meeting for that is all for now. |
Beta Was this translation helpful? Give feedback.
-
Thank you for sharing these!
|
Beta Was this translation helpful? Give feedback.
-
@encukou In addition to these issues I have had at times had to "augment" the C API to perform tasks for which there were not relevant calls. You may want to review them to see which ones are relevant to the API. jpype/native/python/pyjp_module.cpp Line 144 in f38a066 jpype/native/python/pyjp_module.cpp Line 166 in f38a066 jpype/native/python/pyjp_module.cpp Line 199 in f38a066 jpype/native/python/pyjp_module.cpp Line 211 in f38a066 |
Beta Was this translation helpful? Give feedback.
-
Next up.... The lack of a factory from buffer type to buffer type in the C API was an rough spot. Likely out of scope for your work, but it was an area that created a lot of issue. My version is specialize in that it takes a Python buffer type string and a Java type code and gives back a function, but it could easily be reformulated to go from Python buffer type to Python buffer type strings. jpype/native/common/jp_convert.cpp Line 128 in f38a066 The code is slightly less cursed that the corresponding one in C Python which I could not access through the API at all. So I had to replicate the whole darn thing in my version. (Again sorry for the wish list, but there are a lot of items that have plagued me over the years and I have a fair number of dead bodies that I have to recall where I buried.) |
Beta Was this translation helpful? Give feedback.
-
@encukou So on to evil hacks. jpype/native/python/pyjp_method.cpp Line 401 in f38a066 In this code I was trying to make Java methods compatible with Python ones such that they shared the API enough that they were always guaranteed to be recognized by tab completion engines. At the time, I extended the Python method function class from my own, but that class was not marked as a base class so I had to flip the flags in the function class, extend it, then flip it back. It is still unclear if extending the type as the user who was directing the work was pointing me in the wrong direction (since he was trying to get jedi to work). But it points to usual problem that if something is assuming concrete types rather than protocols the evil hacks end up getting used. |
Beta Was this translation helpful? Give feedback.
-
@encukou Next up nearly completely intractable problems.... My single worst issue is how to deal with multiple garbage collection systems. Java is a garbage collected language, and Python is garbage collected, but neither of them have a plug in to support foreign managed objects. This causes several sets of very complex issues, (some of them I solved and some I have no clue how to deal with).
Line 182 in f38a066
|
Beta Was this translation helpful? Give feedback.
-
And then there is the slice bug.
One idiom that we used in JPype is the simple check of did the user type |
Beta Was this translation helpful? Give feedback.
-
So thus far I have only been discussing "negatives" while there are a few things that I see that are very positive in the C Python API that I would like to see more of. First up, I made the effort to convert all my C implementations to heap types use specifications, rather than the older fixed types were some static memory is being used. I really liked the move from static structure to heaps and it when fairly smoothly except for a few corner cases were static structures would allowed things that were prohibited by heap types. Those limitations required me to create the heap type then alter the slot afterward. That said I found the heap type interface to be much better and safe now the memory was controlled by Python and thus allows easier changes behind the scenes. I would like this to expand throughout the API such that rather than having things that may be a pointer or a direct reference to a static structure, everything should be pointer types only so that they are consistent and it is irrelevant if they are heap or statically typed. |
Beta Was this translation helpful? Give feedback.
-
Next request.... This is not really a C API, but certainly a request toward standardization. Please standardize the Python byte codes and compiled class formats like Java has done. One of the key things that I have been trying to achieve is to make it so a compiled Python file with customizers for Java classes to be stored in the Jar files directly. If I have to place a different jar file for each Python version then it becomes a huge headache. My understanding is the Python byte codes are version specific by architecture portable (I could be wrong). Having a byte code system which is at least backward compatible (with a version number so that it is always clear which interpretation) would help towards being able to ship embedded Python which would be helpful for Android. |
Beta Was this translation helpful? Give feedback.
-
Next up, missing destructors on POSIX thread of course allow a dtor to be attached to a key using
The code for this is not very complex. If the system doesn't support fibers, then it is fine because it will leak which is what we are already doing.
|
Beta Was this translation helpful? Give feedback.
-
One entirely off the wall API discussion: I have been trying for a while to port the Java method of dealing with native referencing into Python (done about 3 different attempts). I am not sure this would help others as they generally end up using heap objects to hold the local reference frames or anonymous union hacks in C11. The concept is simple, at the start of a function you declare a frame which will hold all references (and declares a goto statement where all the exceptions will be handled if I want to merge exception handling in), which is passed to the corresponding methods. (though it can be hidden if you use a tss). Instead of passing back a borrowed or new reference, the reference is held in frame for the user. The user can add their own hard reference to it to hold it, call "keep" in a return statement to push the object to the enclosed outer local reference frame, or do nothing in which case it will be destroyed with all the local references. It works well with gcc in which you have the equivalent of a finally statement which removes logic from the function "exit" and "keep" routines. It can run without the finally, but then you have to be careful no never return without calling the keep or exit routine. It can be made to play nice with current system (if you are using the tss so you don't have an extra argument) though I am sure there are edge cases. If is unfortunately slightly slower because it needs to clean up the references with a for loop rather than having the user directly kill the references. (the extra instructions to check the remaining items costs a bit over hard coding). The anonymous union version will of cross crash if you do a for loop and fail to set up an inner frame as it will exhaust the frame slots. The heap version are slower as it has to pull from the local frame pool each call. The macro magic is just written out copies of regular functions in most cases so it is possible create heap frames and use it without the macros. The result is Python C code that reads a bit more like Java/C++ in which there are not endless levels of if statements, and no need for the user to see the referencing. However, I fear that such a system is just too far from the current C API to ever be considered. I have been writing it for my own vanity project (a compiled language like Java which supports Python like protocols and views), but if it were something that Python could consider I could try to put in some effort. |
Beta Was this translation helpful? Give feedback.
-
@encukou Searching through the code I found another set of rough spots. That is in general there are no methods to create new objects for certain primitives like longs with an extension class. So for example when I need to create a JLong which is derived from long (which just the added memory for a slot and the new meta class). I end up having to replicate portions of the code.
First I have to call |
Beta Was this translation helpful? Give feedback.
-
There is now a wider effort for mapping out C API issues at: https://github.com/capi-workgroup/problems/issues |
Beta Was this translation helpful? Give feedback.
-
Hello,
I'm figuring out a strategy for the future of Python's C-API, and as one of the goals I'd like to make it friendly for non-C languages. But since I mostly deal with C & Python, I'd like to ask you for any suggestions, pain points or comments on how do better to that.
Would you like to help?
I started a Google doc to collect notes, please feel free to comment there, or here, or suggest a better place.
Thank you for your time!
Beta Was this translation helpful? Give feedback.
All reactions