Index: src/sas/sascalc/calculator/c_extensions/sld2i_module.c
===================================================================
--- src/sas/sascalc/calculator/c_extensions/sld2i_module.c	(revision 952ea1fd0d931d2eae09831204ea057abfe5450f)
+++ src/sas/sascalc/calculator/c_extensions/sld2i_module.c	(revision 7ba64705ddaa18ab8bce14ae2ac2e767b23eb313)
@@ -16,20 +16,24 @@
 #endif
 
-
-// Utilities
-#define INVECTOR(obj,buf,len)										\
-    do { \
-        int err = PyObject_AsReadBuffer(obj, (const void **)(&buf), &len); \
-        if (err < 0) return NULL; \
-        len /= sizeof(*buf); \
-    } while (0)
-
-#define OUTVECTOR(obj,buf,len) \
-    do { \
-        int err = PyObject_AsWriteBuffer(obj, (void **)(&buf), &len); \
-        if (err < 0) return NULL; \
-        len /= sizeof(*buf); \
-    } while (0)
-
+// Vector binding glue
+#if (PY_VERSION_HEX > 0x03000000) && !defined(Py_LIMITED_API)
+  // Assuming that a view into a writable vector points to a 
+  // non-changing pointer for the duration of the C call, capture 
+  // the view pointer and immediately free the view.
+  #define VECTOR(VEC_obj, VEC_buf, VEC_len) do { \
+    Py_buffer VEC_view; \
+    int VEC_err = PyObject_GetBuffer(VEC_obj, &VEC_view, PyBUF_WRITABLE|PyBUF_FORMAT); \
+    if (VEC_err < 0 || sizeof(*VEC_buf) != VEC_view.itemsize) return NULL; \
+    VEC_buf = (typeof(VEC_buf))VEC_view.buf; \
+    VEC_len = VEC_view.len/sizeof(*VEC_buf); \
+    PyBuffer_Release(&VEC_view); \
+  } while (0)
+#else
+  #define VECTOR(VEC_obj, VEC_buf, VEC_len) do { \
+    int VEC_err = PyObject_AsWriteBuffer(VEC_obj, (void **)(&VEC_buf), &VEC_len); \
+    if (VEC_err < 0) return NULL; \
+    VEC_len /= sizeof(*VEC_buf); \
+  } while (0)
+#endif
 
 /**
@@ -76,12 +80,12 @@
 	//printf("new GenI\n");
 	if (!PyArg_ParseTuple(args, "iOOOOOOOOddd", &is_avg, &x_val_obj, &y_val_obj, &z_val_obj, &sldn_val_obj, &mx_val_obj, &my_val_obj, &mz_val_obj, &vol_pix_obj, &inspin, &outspin, &stheta)) return NULL;
-	INVECTOR(x_val_obj, x_val, n_x);
-	INVECTOR(y_val_obj, y_val, n_y);
-	INVECTOR(z_val_obj, z_val, n_z);
-	INVECTOR(sldn_val_obj, sldn_val, n_sld);
-	INVECTOR(mx_val_obj, mx_val, n_mx);
-	INVECTOR(my_val_obj, my_val, n_my);
-	INVECTOR(mz_val_obj, mz_val, n_mz);
-	INVECTOR(vol_pix_obj, vol_pix, n_vol_pix);
+	VECTOR(x_val_obj, x_val, n_x);
+	VECTOR(y_val_obj, y_val, n_y);
+	VECTOR(z_val_obj, z_val, n_z);
+	VECTOR(sldn_val_obj, sldn_val, n_sld);
+	VECTOR(mx_val_obj, mx_val, n_mx);
+	VECTOR(my_val_obj, my_val, n_my);
+	VECTOR(mz_val_obj, mz_val, n_mz);
+	VECTOR(vol_pix_obj, vol_pix, n_vol_pix);
 	sld2i = PyMem_Malloc(sizeof(GenI));
 	//printf("sldi:%p\n", sld2i);
@@ -111,7 +115,7 @@
 	if (!PyArg_ParseTuple(args, "OOOO",  &gen_obj, &qx_obj, &qy_obj, &I_out_obj)) return NULL;
 	sld2i = (GenI *)PyCapsule_GetPointer(gen_obj, "GenI");
-	INVECTOR(qx_obj, qx, n_qx);
-	INVECTOR(qy_obj, qy, n_qy);
-	OUTVECTOR(I_out_obj, I_out, n_out);
+	VECTOR(qx_obj, qx, n_qx);
+	VECTOR(qy_obj, qy, n_qy);
+	VECTOR(I_out_obj, I_out, n_out);
 	//printf("qx, qy, I_out: %d %d %d, %d %d %d\n", qx, qy, I_out, n_qx, n_qy, n_out);
 
@@ -139,6 +143,6 @@
 	if (!PyArg_ParseTuple(args, "OOO",  &gen_obj, &q_obj, &I_out_obj)) return NULL;
 	sld2i = (GenI *)PyCapsule_GetPointer(gen_obj, "GenI");
-	INVECTOR(q_obj, q, n_q);
-	OUTVECTOR(I_out_obj, I_out, n_out);
+	VECTOR(q_obj, q, n_q);
+	VECTOR(I_out_obj, I_out, n_out);
 
 	// Sanity check
Index: src/sas/sascalc/pr/c_extensions/Cinvertor.c
===================================================================
--- src/sas/sascalc/pr/c_extensions/Cinvertor.c	(revision 952ea1fd0d931d2eae09831204ea057abfe5450f)
+++ src/sas/sascalc/pr/c_extensions/Cinvertor.c	(revision 7ba64705ddaa18ab8bce14ae2ac2e767b23eb313)
@@ -14,23 +14,29 @@
 #include <structmember.h>
 
+// Vector binding glue
+#if (PY_VERSION_HEX > 0x03000000) && !defined(Py_LIMITED_API)
+  // Assuming that a view into a writable vector points to a
+  // non-changing pointer for the duration of the C call, capture
+  // the view pointer and immediately free the view.
+  #define VECTOR(VEC_obj, VEC_buf, VEC_len) do { \
+    Py_buffer VEC_view; \
+    int VEC_err = PyObject_GetBuffer(VEC_obj, &VEC_view, PyBUF_WRITABLE|PyBUF_FORMAT); \
+    if (VEC_err < 0 || sizeof(*VEC_buf) != VEC_view.itemsize) return NULL; \
+    VEC_buf = (typeof(VEC_buf))VEC_view.buf; \
+    VEC_len = VEC_view.len/sizeof(*VEC_buf); \
+    PyBuffer_Release(&VEC_view); \
+  } while (0)
+#else
+  #define VECTOR(VEC_obj, VEC_buf, VEC_len) do { \
+    int VEC_err = PyObject_AsWriteBuffer(VEC_obj, (void **)(&VEC_buf), &VEC_len); \
+    if (VEC_err < 0) return NULL; \
+    VEC_len /= sizeof(*VEC_buf); \
+  } while (0)
+#endif
+
 #include "invertor.h"
 
 /// Error object for raised exceptions
 PyObject * CinvertorError;
-
-#define INVECTOR(obj,buf,len)										\
-    do { \
-        int err = PyObject_AsReadBuffer(obj, (const void **)(&buf), &len); \
-        if (err < 0) return NULL; \
-        len /= sizeof(*buf); \
-    } while (0)
-
-#define OUTVECTOR(obj,buf,len) \
-    do { \
-        int err = PyObject_AsWriteBuffer(obj, (void **)(&buf), &len); \
-        if (err < 0) return NULL; \
-        len /= sizeof(*buf); \
-    } while (0)
-
 
 // Class definition
@@ -100,5 +106,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,data,ndata);
+	VECTOR(data_obj,data,ndata);
 
 	free(self->params.x);
@@ -132,5 +138,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj, data, ndata);
+	VECTOR(data_obj, data, ndata);
 
 	// Check that the input array is large enough
@@ -165,5 +171,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,data,ndata);
+	VECTOR(data_obj,data,ndata);
 
 	free(self->params.y);
@@ -197,5 +203,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj, data, ndata);
+	VECTOR(data_obj, data, ndata);
 
 	// Check that the input array is large enough
@@ -230,5 +236,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,data,ndata);
+	VECTOR(data_obj,data,ndata);
 
 	free(self->params.err);
@@ -262,5 +268,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj, data, ndata);
+	VECTOR(data_obj, data, ndata);
 
 	// Check that the input array is large enough
@@ -518,5 +524,5 @@
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
 
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
     // PyList of residuals
@@ -569,5 +575,5 @@
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
 
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	// Should create this list only once and refill it
@@ -610,5 +616,5 @@
 
 	if (!PyArg_ParseTuple(args, "Od", &data_obj, &q)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	iq_value = iq(pars, self->params.d_max, (int)npars, q);
@@ -635,5 +641,5 @@
 
 	if (!PyArg_ParseTuple(args, "Od", &data_obj, &q)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	iq_value = iq_smeared(pars, self->params.d_max, (int)npars,
@@ -660,5 +666,5 @@
 
 	if (!PyArg_ParseTuple(args, "Od", &data_obj, &r)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	pr_value = pr(pars, self->params.d_max, (int)npars, r);
@@ -687,5 +693,5 @@
 
 	if (!PyArg_ParseTuple(args, "OOd", &data_obj, &err_obj, &r)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	if (err_obj == Py_None) {
@@ -693,5 +699,5 @@
 		pr_err_value = 0.0;
 	} else {
-		OUTVECTOR(err_obj,pars_err,npars2);
+		VECTOR(err_obj,pars_err,npars2);
 		pr_err(pars, pars_err, self->params.d_max, (int)npars, r, &pr_value, &pr_err_value);
 	}
@@ -727,5 +733,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	oscill = reg_term(pars, self->params.d_max, (int)npars, 100);
@@ -748,5 +754,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	count = npeaks(pars, self->params.d_max, (int)npars, 100);
@@ -769,5 +775,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	fraction = positive_integral(pars, self->params.d_max, (int)npars, 100);
@@ -793,6 +799,6 @@
 
 	if (!PyArg_ParseTuple(args, "OO", &data_obj, &err_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
-	OUTVECTOR(err_obj,pars_err,npars2);
+	VECTOR(data_obj,pars,npars);
+	VECTOR(err_obj,pars_err,npars2);
 
 	fraction = positive_errors(pars, pars_err, self->params.d_max, (int)npars, 51);
@@ -814,5 +820,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	value = rg(pars, self->params.d_max, (int)npars, 101);
@@ -834,5 +840,5 @@
 
 	if (!PyArg_ParseTuple(args, "O", &data_obj)) return NULL;
-	OUTVECTOR(data_obj,pars,npars);
+	VECTOR(data_obj,pars,npars);
 
 	value = 4.0*acos(-1.0)*int_pr(pars, self->params.d_max, (int)npars, 101);
@@ -875,6 +881,6 @@
 
 	if (!PyArg_ParseTuple(args, "iiOO", &nfunc, &nr, &a_obj, &b_obj)) return NULL;
-	OUTVECTOR(a_obj,a,n_a);
-	OUTVECTOR(b_obj,b,n_b);
+	VECTOR(a_obj,a,n_a);
+	VECTOR(b_obj,b,n_b);
 
 	assert(n_b>=nfunc);
@@ -948,6 +954,6 @@
 
 	if (!PyArg_ParseTuple(args, "iiOO", &nfunc, &nr, &a_obj, &cov_obj)) return NULL;
-	OUTVECTOR(a_obj,a,n_a);
-	OUTVECTOR(cov_obj,inv_cov,n_cov);
+	VECTOR(a_obj,a,n_a);
+	VECTOR(cov_obj,inv_cov,n_cov);
 
 	assert(n_cov>=nfunc*nfunc);
@@ -982,5 +988,5 @@
 
 	if (!PyArg_ParseTuple(args, "iiO", &nfunc, &nr, &a_obj)) return NULL;
-	OUTVECTOR(a_obj,a,n_a);
+	VECTOR(a_obj,a,n_a);
 
 	assert(n_a>=nfunc*(nr+self->params.npoints));
