You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm concerned that the automated process pythonnet uses to generate the interop[version].cs file might be flawed. This is the relevant snippet from object.h
unsigned int tp_version_tag;
destructor tp_finalize;
vectorcallfunc tp_vectorcall;
/* bpo-37250: kept for backwards compatibility in CPython 3.8 only */
Py_DEPRECATED(3.8) int (*tp_print)(PyObject *, FILE *, int);
this is how I mapped those fields in my handmade interop38.cs
public static int tp_version_tag = 0;
public static int tp_finalize = 0;
public static int tp_vectorcall = 0;
public static int tp_print = 0;
public static int am_await = 0;
but here's how the auto-generated interop38.cs maps them
public static int tp_version_tag = 0;
public static int tp_finalize = 0;
public static int tp_vectorcall = 0;
public static int am_await = 0;
Notice the missing public static int tp_print = 0;
I'm thinking that the Py_DEPRECATED(3.8) int (*tp_print)(PyObject *, FILE *, int); messed up the auto-gen technique? Won't all fields following tp_vectorcall be offset incorrectly due to this?
[EDITED]I think Py_ssize_t tp_vectorcall_offset; replaced the previous location of public static int tp_print = 0;, and then
vectorcallfunc tp_vectorcall;
Py_DEPRECATED(3.8) int (*tp_print)(PyObject *, FILE *, int);
were added after public static int tp_finalize = 0;
Since qualname is way at the end, I think I can come up with a test to show that the auto-gen'ed offset for it (qualname) is either correct or incorrect.
typemanager.cs assigns the type's name into qualname via this code
#if PYTHON3
// For python3 we leak two objects. One for the ASCII representation
// required for tp_name, and another for the Unicode representation
// for ht_name.
IntPtr temp = Runtime.PyBytes_FromString(name);
IntPtr raw = Runtime.PyBytes_AS_STRING(temp);
temp = Runtime.PyUnicode_FromString(name);
#elif PYTHON2
IntPtr temp = Runtime.PyString_FromString(name);
IntPtr raw = Runtime.PyString_AsString(temp);
#endif
Marshal.WriteIntPtr(type, TypeOffset.tp_name, raw);
Marshal.WriteIntPtr(type, TypeOffset.name, temp);
#if PYTHON3
Marshal.WriteIntPtr(type, TypeOffset.qualname, temp);
#endif
The repo's current interop38.cs results in 0x358 as the value of TypeOffset.qualname. But this is wrong...it should be 0x360.
You can see it crash in the REPL
>>> import clr
>>> import System
>>> System.String.__qualname__
so I'm guessing that geninterop.py threw a warning when interop38.cs was generated. I'm having trouble running geninterop.py on my Windows machine, but I can see that clang.exe did the preprocess step and then pycparser isn't liking the mixture of slashes and backslashes.
But ignoring my Windows issues, there's a problem in the automated workflow producing interop38.cs.
Activity
filmor commentedon Nov 27, 2019
If I get https://docs.python.org/3/c-api/typeobj.html#c.PyVectorcall_Call correctly,
tp_vectorcallreplacestp_print. I'll check what happens in this header.Jeff17Robbins commentedon Nov 27, 2019
[EDITED]I think
Py_ssize_t tp_vectorcall_offset;replaced the previous location ofpublic static int tp_print = 0;, and thenwere added after
public static int tp_finalize = 0;Since
qualnameis way at the end, I think I can come up with a test to show that the auto-gen'ed offset for it (qualname) is either correct or incorrect.Jeff17Robbins commentedon Nov 27, 2019
typemanager.csassigns the type's name intoqualnamevia this codeThe repo's current
interop38.csresults in0x358as the value ofTypeOffset.qualname. But this is wrong...it should be0x360.You can see it crash in the REPL
[-]interop38.cs might have a problem[/-][+]interop38.cs has a problem[/+]Jeff17Robbins commentedon Nov 27, 2019
If you manually fix
interop38.csto add the missing fieldJeff17Robbins commentedon Nov 27, 2019
pycparser doesn't support
__attribute__(and presumably also doesn't support__declspec)https://github.com/eliben/pycparser/wiki/FAQ#does-pycparser-support-gnuvisual-c-extensions
so I'm guessing that
geninterop.pythrew a warning wheninterop38.cswas generated. I'm having trouble runninggeninterop.pyon my Windows machine, but I can see thatclang.exedid the preprocess step and thenpycparserisn't liking the mixture of slashes and backslashes.But ignoring my Windows issues, there's a problem in the automated workflow producing
interop38.cs.Jeff17Robbins commentedon Nov 27, 2019
I got
geninterop.pyto run on Windows by adding more things for clang to ignore. But still was missingtp_print. Then I realized what was wrong:the
visitfunction was missing a case forc_ast.FuncDecl, that's whatint (*tp_print)(PyObject *, FILE *, int);has inside thec_ast.PtrDecl.I added this case to
visitand implemented it as
And now I get the correct mapping struct, with a
tp_printmember.So this is a bug in
geninterop.py.For those curious, this is how
pycparserprints out the node fortp_print:[-]interop38.cs has a problem[/-][+]geninterop.py doesn't handle c_ast.FuncDecl; creates broken interop38.cs[/+]filmor commentedon Nov 28, 2019
Fixed in 627cac0.