|
1 | | -using System; |
| 1 | +using System; |
2 | 2 | using System.Runtime.InteropServices; |
3 | 3 | using System.Security; |
4 | 4 | using System.Text; |
@@ -274,19 +274,17 @@ internal static void Initialize() |
274 | 274 |
|
275 | 275 | Error = new IntPtr(-1); |
276 | 276 |
|
277 | | -#if PYTHON3 |
278 | 277 | IntPtr dllLocal = IntPtr.Zero; |
279 | 278 | if (PythonDll != "__Internal") |
280 | 279 | { |
281 | | - NativeMethods.LoadLibrary(PythonDll); |
| 280 | + dllLocal = NativeMethods.LoadLibrary(PythonDll); |
282 | 281 | } |
283 | 282 | _PyObject_NextNotImplemented = NativeMethods.GetProcAddress(dllLocal, "_PyObject_NextNotImplemented"); |
284 | 283 | #if !(MONO_LINUX || MONO_OSX) |
285 | 284 | if (dllLocal != IntPtr.Zero) |
286 | 285 | { |
287 | 286 | NativeMethods.FreeLibrary(dllLocal); |
288 | 287 | } |
289 | | -#endif |
290 | 288 | #endif |
291 | 289 |
|
292 | 290 | // Initialize modules that depend on the runtime class. |
@@ -349,8 +347,8 @@ internal static int AtExit() |
349 | 347 |
|
350 | 348 | #if PYTHON3 |
351 | 349 | internal static IntPtr PyBytesType; |
352 | | - internal static IntPtr _PyObject_NextNotImplemented; |
353 | 350 | #endif |
| 351 | + internal static IntPtr _PyObject_NextNotImplemented; |
354 | 352 |
|
355 | 353 | internal static IntPtr PyNotImplemented; |
356 | 354 | internal const int Py_LT = 0; |
@@ -780,6 +778,21 @@ internal static string PyObject_GetTypeName(IntPtr op) |
780 | 778 | return Marshal.PtrToStringAnsi(ppName); |
781 | 779 | } |
782 | 780 |
|
| 781 | + /// <summary> |
| 782 | + /// Test whether the Python object is an iterable. |
| 783 | + /// </summary> |
| 784 | + internal static bool PyObject_IsIterable(IntPtr pointer) |
| 785 | + { |
| 786 | + var ob_type = Marshal.ReadIntPtr(pointer, ObjectOffset.ob_type); |
| 787 | +#if PYTHON2 |
| 788 | + long tp_flags = Marshal.ReadInt64(ob_type, TypeOffset.tp_flags); |
| 789 | + if ((tp_flags & TypeFlags.HaveIter) == 0) |
| 790 | + return false; |
| 791 | +#endif |
| 792 | + IntPtr tp_iter = Marshal.ReadIntPtr(ob_type, TypeOffset.tp_iter); |
| 793 | + return tp_iter != IntPtr.Zero; |
| 794 | + } |
| 795 | + |
783 | 796 | [DllImport(PythonDll, CallingConvention = CallingConvention.Cdecl)] |
784 | 797 | internal static extern int PyObject_HasAttrString(IntPtr pointer, string name); |
785 | 798 |
|
@@ -1425,17 +1438,17 @@ internal static bool PyTuple_Check(IntPtr ob) |
1425 | 1438 | // Python iterator API |
1426 | 1439 | //==================================================================== |
1427 | 1440 |
|
1428 | | -#if PYTHON2 |
1429 | | - [DllImport(PythonDll, CallingConvention = CallingConvention.Cdecl)] |
1430 | | - internal static extern bool PyIter_Check(IntPtr pointer); |
1431 | | -#elif PYTHON3 |
1432 | 1441 | internal static bool PyIter_Check(IntPtr pointer) |
1433 | 1442 | { |
1434 | | - var ob_type = (IntPtr)Marshal.PtrToStructure(pointer + ObjectOffset.ob_type, typeof(IntPtr)); |
1435 | | - IntPtr tp_iternext = ob_type + TypeOffset.tp_iternext; |
1436 | | - return tp_iternext != null && tp_iternext != _PyObject_NextNotImplemented; |
1437 | | - } |
| 1443 | + var ob_type = Marshal.ReadIntPtr(pointer, ObjectOffset.ob_type); |
| 1444 | +#if PYTHON2 |
| 1445 | + long tp_flags = Marshal.ReadInt64(ob_type, TypeOffset.tp_flags); |
| 1446 | + if ((tp_flags & TypeFlags.HaveIter) == 0) |
| 1447 | + return false; |
1438 | 1448 | #endif |
| 1449 | + IntPtr tp_iternext = Marshal.ReadIntPtr(ob_type, TypeOffset.tp_iternext); |
| 1450 | + return tp_iternext != IntPtr.Zero && tp_iternext != _PyObject_NextNotImplemented; |
| 1451 | + } |
1439 | 1452 |
|
1440 | 1453 | [DllImport(PythonDll, CallingConvention = CallingConvention.Cdecl)] |
1441 | 1454 | internal static extern IntPtr PyIter_Next(IntPtr pointer); |
|
0 commit comments