Issue #7767: Add new C-API function PyLong_AsLongLongAndOverflow, a
long long variant of PyLong_AsLongAndOverflow.  Patch by Case Van
Horsen.
diff --git a/Objects/longobject.c b/Objects/longobject.c
index 51442d3..4290f4e 100644
--- a/Objects/longobject.c
+++ b/Objects/longobject.c
@@ -821,6 +821,7 @@
  */
 
 #define IS_LITTLE_ENDIAN (int)*(unsigned char*)&one
+#define PY_ABS_LLONG_MIN	(0-(unsigned PY_LONG_LONG)PY_LLONG_MIN)
 
 /* Create a new long int object from a C PY_LONG_LONG int. */
 
@@ -1023,6 +1024,109 @@
 	}
 	return x * sign;
 }
+
+/* Get a C long long int from a Python long or Python int object.
+   On overflow, returns -1 and sets *overflow to 1 or -1 depending
+   on the sign of the result.  Otherwise *overflow is 0.
+
+   For other errors (e.g., type error), returns -1 and sets an error
+   condition.
+*/
+
+PY_LONG_LONG
+PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
+{
+	/* This version by Tim Peters */
+	register PyLongObject *v;
+	unsigned PY_LONG_LONG x, prev;
+	PY_LONG_LONG res;
+	Py_ssize_t i;
+	int sign;
+	int do_decref = 0; /* if nb_int was called */
+
+	*overflow = 0;
+	if (vv == NULL) {
+		PyErr_BadInternalCall();
+		return -1;
+	}
+
+	if (PyInt_Check(vv))
+		return PyInt_AsLong(vv);
+
+	if (!PyLong_Check(vv)) {
+		PyNumberMethods *nb;
+		nb = vv->ob_type->tp_as_number;
+		if (nb == NULL || nb->nb_int == NULL) {
+			PyErr_SetString(PyExc_TypeError,
+					"an integer is required");
+			return -1;
+		}
+		vv = (*nb->nb_int) (vv);
+		if (vv == NULL)
+			return -1;
+		do_decref = 1;
+		if(PyInt_Check(vv)) {
+			res = PyInt_AsLong(vv);
+			goto exit;
+		}
+		if (!PyLong_Check(vv)) {
+			Py_DECREF(vv);
+			PyErr_SetString(PyExc_TypeError,
+					"nb_int should return int object");
+			return -1;
+		}
+	}
+
+	res = -1;
+	v = (PyLongObject *)vv;
+	i = Py_SIZE(v);
+
+	switch (i) {
+	case -1:
+		res = -(sdigit)v->ob_digit[0];
+		break;
+	case 0:
+		res = 0;
+		break;
+	case 1:
+		res = v->ob_digit[0];
+		break;
+	default:
+		sign = 1;
+		x = 0;
+		if (i < 0) {
+			sign = -1;
+			i = -(i);
+		}
+		while (--i >= 0) {
+			prev = x;
+			x = (x << PyLong_SHIFT) + v->ob_digit[i];
+			if ((x >> PyLong_SHIFT) != prev) {
+				*overflow = sign;
+				goto exit;
+			}
+		}
+		/* Haven't lost any bits, but casting to long requires extra
+		 * care (see comment above).
+		 */
+		if (x <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) {
+			res = (PY_LONG_LONG)x * sign;
+		}
+		else if (sign < 0 && x == PY_ABS_LLONG_MIN) {
+			res = PY_LLONG_MIN;
+		}
+		else {
+			*overflow = sign;
+			/* res is already set to -1 */
+		}
+	}
+ exit:
+	if (do_decref) {
+		Py_DECREF(vv);
+	}
+	return res;
+}
+
 #undef IS_LITTLE_ENDIAN
 
 #endif /* HAVE_LONG_LONG */