]> rtime.felk.cvut.cz Git - opencv.git/commitdiff
Added doconly decls, finishing #4
authorjamesb <jamesb@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Mon, 29 Mar 2010 22:39:36 +0000 (22:39 +0000)
committerjamesb <jamesb@73c94f0f-984f-4a5f-82bc-2d8db8d8ee08>
Mon, 29 Mar 2010 22:39:36 +0000 (22:39 +0000)
git-svn-id: https://code.ros.org/svn/opencv/trunk@2940 73c94f0f-984f-4a5f-82bc-2d8db8d8ee08

opencv/interfaces/python/api
opencv/interfaces/python/cv.cpp
opencv/interfaces/python/gen.py

index f5cfd7df991a845645e456af93ad00b3b3c4d8b7..d89fe0196ae7198b4d1fc1ba4216491090e92425 100644 (file)
@@ -1654,3 +1654,139 @@ HOGDetectMultiScale CvSeq*
   CvSize cell_size cvSize(8,8)
   int nbins 9
   int gammaCorrection 1
+
+# These functions are handwritten in cv.cpp; they appear here as 'doconly' declarations
+# so that their documentation can be auto-generated
+ApproxPoly  /doconly
+  cvarrseq src_seq
+  CvMemStorage storage
+  int method
+  double parameter 0.0
+  int parameter2 0
+CalcEMD2  /doconly
+  CvArr signature1
+  CvArr signature2
+  int distance_type
+  PyCallableObject* distance_func NULL
+  CvArr cost_matrix NULL
+  CvArr flow NULL
+  float lower_bound 0.0
+  PyObject* userdata NULL
+CalcOpticalFlowPyrLK currFeatures,status,track_error /doconly
+  CvArr prev
+  CvArr curr
+  CvArr prevPyr
+  CvArr currPyr
+  CvPoint2D32f* prevFeatures
+  int count
+  CvSize winSize
+  int level
+  CvTermCriteria criteria
+  int flags
+  CvPoint2D32f* guesses
+  CvPoint2D32f currFeatures /O
+  char status /O
+  float track_error /O
+ClipLine /doconly
+  CvSize imgSize
+  CvPoint pt1
+  CvPoint pt2
+CreateData /doconly
+  CvArr arr
+CreateHist /doconly
+  ints dims
+  int type
+  ranges ranges None
+  int uniform 1
+CreateImageHeader /doconly
+  int size
+  int depth
+  int channels
+CreateImage /doconly
+  int size
+  int depth
+  int channels
+CreateMatHeader /doconly
+  int rows
+  int cols
+  int type
+CreateMat /doconly
+  int rows
+  int cols
+  int type
+CreateMatNDHeader /doconly
+  ints dims
+  int type
+CreateMatND /doconly
+  ints dims
+  int type
+CreateMemStorage /doconly
+  int block_size
+CreateTrackbar /doconly
+  char* trackbar_name
+  char* window_name
+  int value
+  int count
+  PyCallableObject* on_change
+FindChessboardCorners /doconly
+  CvArr image
+  CvSize pattern_size
+  CvPoint2D32fs corners
+  int flags CV_CALIB_CB_ADAPTIVE_THRESH
+FindContours /doconly
+  CvArr image
+  CvMemStorage storage
+  int mode CV_RETR_LIST
+  int method CV_CHAIN_APPROX_SIMPLE
+  CvPoint offset (0,0)
+FitLine /doconly
+  CvArr points
+  int dist_type
+  double param
+  double reps
+  double aeps
+GetDims /doconly
+  CvArr arr
+  ints dims
+GetHuMoments /doconly
+  CvMoments moments
+GetImage /doconly
+  CvMat arr
+GetMat /doconly
+  IplImage arr
+  int allowND 0
+GetMinMaxHistValue /doconly
+  CvHistogram hist
+InitLineIterator /doconly
+  CvArr image
+  CvPoint pt1
+  CvPoint pt2
+  int connectivity 8
+  int left_to_right 0
+LoadImageM /doconly
+  char* filename
+  int iscolor CV_LOAD_IMAGE_COLOR
+LoadImage /doconly
+  char* filename
+  int iscolor CV_LOAD_IMAGE_COLOR
+ReshapeMatND /doconly
+  CvMat arr
+  int new_cn
+  int new_dims
+Reshape /doconly
+  CvArr arr
+  int new_cn
+  int new_dims
+SetData /doconly
+  CvArr arr
+  PyObject* data
+  int step
+SetMouseCallback /doconly
+  char* window_name
+  PyCallableObject* on_mouse
+  PyObject* param None
+Subdiv2DLocate /doconly
+  CvSubdiv2D* subdiv
+  CvPoint2D32f pt
+WaitKey /doconly
+  int delay 0
index 94ded4e8378fd1347ce0d6a805369a440d2e6edb..774d210e71e6c6da88cbf1fb9551124b691d27be 100644 (file)
@@ -90,6 +90,7 @@ struct cvlineiterator_t {
 
 typedef IplImage ROIplImage;
 typedef const CvMat ROCvMat;
+typedef PyObject PyCallableObject;
 
 struct cvmoments_t {
   PyObject_HEAD
@@ -1293,7 +1294,7 @@ static void cvset_specials(void)
 
 static PyTypeObject cvsubdiv2d_Type = {
   PyObject_HEAD_INIT(&PyType_Type)
-  0,                                      /*size*/
+  0,                                          /*size*/
   MODULESTR".cvsubdiv2d",                     /*name*/
   sizeof(cvsubdiv2d_t),                       /*basicsize*/
 };
@@ -1354,6 +1355,18 @@ static void cvsubdiv2dpoint_specials(void)
 /************************************************************************/
 /* convert_to_X: used after PyArg_ParseTuple in the generated code  */
 
+static int convert_to_PyObjectPTR(PyObject *o, PyObject **dst, const char *name = "no_name")
+{
+  *dst = o;
+  return 1;
+}
+
+static int convert_to_PyCallableObjectPTR(PyObject *o, PyObject **dst, const char *name = "no_name")
+{
+  *dst = o;
+  return 1;
+}
+
 static int convert_to_char(PyObject *o, char *dst, const char *name = "no_name")
 {
   if (PyString_Check(o) && PyString_Size(o) == 1) {
@@ -2798,14 +2811,15 @@ static PyObject *fromarray(PyObject *o, int allowND)
 }
 #endif
 
-static PyObject *pycvCreateHist(PyObject *self, PyObject *args)
+static PyObject *pycvCreateHist(PyObject *self, PyObject *args, PyObject *kw)
 {
+  const char *keywords[] = { "dims", "type", "ranges", "uniform", NULL };
   PyObject *dims;
   int type;
   float **ranges = NULL;
   int uniform = 1;
 
-  if (!PyArg_ParseTuple(args, "Oi|O&i", &dims, &type, convert_to_floatPTRPTR, (void*)&ranges, &uniform)) {
+  if (!PyArg_ParseTupleAndKeywords(args, kw, "Oi|O&i", (char**)keywords, &dims, &type, convert_to_floatPTRPTR, (void*)&ranges, &uniform)) {
     return NULL;
   }
   cvhistogram_t *h = PyObject_NEW(cvhistogram_t, &cvhistogram_Type);
@@ -2824,15 +2838,16 @@ static PyObject *pycvCreateHist(PyObject *self, PyObject *args)
   return (PyObject*)h;
 }
 
-static PyObject *pycvInitLineIterator(PyObject *self, PyObject *args)
+static PyObject *pycvInitLineIterator(PyObject *self, PyObject *args, PyObject *kw)
 {
+  const char *keywords[] = { "image", "pt1", "pt2", "connectivity", "left_to_right", NULL };
   CvArr *image;
   CvPoint pt1;
   CvPoint pt2;
   int connectivity = 8;
   int left_to_right = 0;
 
-  if (!PyArg_ParseTuple(args, "O&O&O&|ii",
+  if (!PyArg_ParseTupleAndKeywords(args, kw, "O&O&O&|ii", (char**)keywords,
                         convert_to_CvArr, &image,
                         convert_to_CvPoint, &pt1,
                         convert_to_CvPoint, &pt2,
@@ -3297,16 +3312,15 @@ void OnChange(int pos, void *param)
   PyGILState_Release(gstate);
 }
 
-static PyObject *pycvCreateTrackbar(PyObject *self, PyObject *args, PyObject *kw)
+static PyObject *pycvCreateTrackbar(PyObject *self, PyObject *args)
 {
-  const char *keywords[] = { "trackbar_name", "window_name", "value", "count", "on_change", NULL };
   PyObject *on_change;
   char* trackbar_name;
   char* window_name;
   int *value = new int;
   int count;
 
-  if (!PyArg_ParseTupleAndKeywords(args, kw, "ssiiO", (char**)keywords, &trackbar_name, &window_name, value, &count, &on_change))
+  if (!PyArg_ParseTuple(args, "ssiiO", &trackbar_name, &window_name, value, &count, &on_change))
     return NULL;
   if (!PyCallable_Check(on_change)) {
     PyErr_SetString(PyExc_TypeError, "on_change must be callable");
@@ -3452,7 +3466,7 @@ static PyObject *pycvSubdiv2DLocate(PyObject *self, PyObject *args)
   default:
     return (PyObject*)failmsg("Unexpected loc from cvSubdiv2DLocate");
   }
-  return Py_BuildValue("iO", (int)loc, r);;
+  return Py_BuildValue("iO", (int)loc, r);
 }
 
 static PyObject *pycvCalcOpticalFlowPyrLK(PyObject *self, PyObject *args)
@@ -3523,7 +3537,7 @@ static PyObject *pycvCalcOpticalFlowPyrLK(PyObject *self, PyObject *args)
 
 // pt1,pt2 are input and output arguments here
 
-static PyObject *pycvClipLine(PyObject *self, PyObject *args, PyObject *kw)
+static PyObject *pycvClipLine(PyObject *self, PyObject *args)
 {
   CvSize img_size;
   PyObject *pyobj_img_size = NULL;
@@ -3644,7 +3658,7 @@ static PyObject *shareData(PyObject *donor, CvArr *pdonor, CvMat *precipient)
   return recipient;
 }
 
-static PyObject *pycvGetHuMoments(PyObject *self, PyObject *args, PyObject *kw)
+static PyObject *pycvGetHuMoments(PyObject *self, PyObject *args)
 {
   CvMoments* moments;
   PyObject *pyobj_moments = NULL;
@@ -3657,7 +3671,7 @@ static PyObject *pycvGetHuMoments(PyObject *self, PyObject *args, PyObject *kw)
   return Py_BuildValue("ddddddd", r.hu1, r.hu2, r.hu3, r.hu4, r.hu5, r.hu6, r.hu7);
 }
 
-static PyObject *pycvFitLine(PyObject *self, PyObject *args, PyObject *kw)
+static PyObject *pycvFitLine(PyObject *self, PyObject *args)
 {
   cvarrseq points;
   PyObject *pyobj_points = NULL;
@@ -3685,7 +3699,7 @@ static PyObject *pycvFitLine(PyObject *self, PyObject *args, PyObject *kw)
     return Py_BuildValue("dddddd", r[0], r[1], r[2], r[3], r[4], r[5]);
 }
 
-static PyObject *pycvGetMinMaxHistValue(PyObject *self, PyObject *args, PyObject *kw)
+static PyObject *pycvGetMinMaxHistValue(PyObject *self, PyObject *args)
 {
   CvHistogram* hist;
   PyObject *pyobj_hist = NULL;
@@ -3765,38 +3779,6 @@ static PyMethodDef methods[] = {
   {"fromarray", (PyCFunction)pycvfromarray, METH_KEYWORDS, "fromarray(array) -> cvmatnd"},
 #endif
 
-  {"ApproxPoly", (PyCFunction)pycvApproxPoly, METH_KEYWORDS, "ApproxPoly(src_seq, storage, method, parameter=0, parameter2=0) -> None"},
-  {"CalcEMD2", (PyCFunction)pycvCalcEMD2, METH_KEYWORDS, "CalcEMD2(signature1, signature2, distance_type, distance_func = None, cost_matrix=None, flow=None, lower_bound=None, userdata = None) -> float"},
-  {"CalcOpticalFlowPyrLK", pycvCalcOpticalFlowPyrLK, METH_VARARGS, "CalcOpticalFlowPyrLK(prev, curr, prev_pyr, curr_pyr, prev_features, CvSize win_size, int level, criteria, flags, guesses = None) -> (curr_features, status, track_error)"},
-  {"ClipLine", (PyCFunction)pycvClipLine, METH_KEYWORDS, "ClipLine(img, pt1, pt2) -> (clipped_pt1, clipped_pt2)"},
-  {"CreateData", pycvCreateData, METH_VARARGS, "CreateData(arr) -> None"},
-  {"CreateHist", pycvCreateHist, METH_VARARGS, "CreateHist(dims, type, ranges, uniform = 1) -> hist"},
-  {"CreateImageHeader", pycvCreateImageHeader, METH_VARARGS, "CreateImageHeader(size, depth, channels) -> image"},
-  {"CreateImage", pycvCreateImage, METH_VARARGS, "CreateImage(size, depth, channels) -> image"},
-  {"CreateMatHeader", pycvCreateMatHeader, METH_VARARGS, "CreateMatHeader(rows, cols, type) -> mat"},
-  {"CreateMatNDHeader", pycvCreateMatNDHeader, METH_VARARGS, "CreateMatNDHeader(dims, type) -> matnd"},
-  {"CreateMatND", pycvCreateMatND, METH_VARARGS, "CreateMatND(dims, type) -> matnd"},
-  {"CreateMat", pycvCreateMat, METH_VARARGS, "CreateMat(row, cols, type) -> mat"},
-  {"CreateMemStorage", pycvCreateMemStorage, METH_VARARGS, "CreateMemStorage(block_size) -> memstorage"},
-  {"CreateTrackbar", (PyCFunction)pycvCreateTrackbar, METH_KEYWORDS, "CreateTrackbar(trackbar_name, window_name, value, count, on_change) -> None"},
-  {"FindChessboardCorners", (PyCFunction)pycvFindChessboardCorners, METH_KEYWORDS, "FindChessboardCorners(image, pattern_size, flags=CV_CALIB_CB_ADAPTIVE_THRESH) -> success,corners"},
-  {"FindContours", (PyCFunction)pycvFindContours, METH_KEYWORDS, "FindContours(image, storage, mode=CV_RETR_LIST, method=CV_CHAIN_APPROX_SIMPLE, offset=(0, 0)) -> cvseq"},
-  {"FitLine", (PyCFunction)pycvFitLine, METH_KEYWORDS, "FitLine(points, dist_type, param, reps, aeps) -> line"},
-  {"GetDims", pycvGetDims, METH_VARARGS, "GetDims(arr) -> dims"},
-  {"GetHuMoments", (PyCFunction)pycvGetHuMoments, METH_KEYWORDS, "GetHuMoments(cvmoments) -> (h1, h2, h3, h4, h5, h5, h7)"},
-  {"GetImage", pycvGetImage, METH_VARARGS, "GetImage(cvmat) -> image"},
-  {"GetMat", (PyCFunction)pycvGetMat, METH_KEYWORDS, "GetMat(image, allowND=0) -> cvmat"},
-  {"GetMinMaxHistValue", (PyCFunction)pycvGetMinMaxHistValue, METH_KEYWORDS, "GetMinMaxHistValue(hist) -> min_val,max_val,min_loc,max_loc"},
-  {"InitLineIterator", pycvInitLineIterator, METH_VARARGS, "InitLineIterator(image, pt1, pt2, connectivity=8, left_to_right=0) -> None"},
-  {"LoadImageM", (PyCFunction)pycvLoadImageM, METH_KEYWORDS, "LoadImageM(filename, iscolor=CV_LOAD_IMAGE_COLOR)"},
-  {"LoadImage", (PyCFunction)pycvLoadImage, METH_KEYWORDS, "LoadImage(filename, iscolor=CV_LOAD_IMAGE_COLOR)"},
-  {"ReshapeMatND", pycvReshapeMatND, METH_VARARGS, "Reshape(arr, new_cn, new_dims) -> matnd"},
-  {"Reshape", pycvReshape, METH_VARARGS, "Reshape(arr, new_cn, new_rows=0) -> cvmat"},
-  {"SetData", pycvSetData, METH_VARARGS, "SetData(arr, data, step)"},
-  {"SetMouseCallback", (PyCFunction)pycvSetMouseCallback, METH_KEYWORDS, "SetMouseCallback(window_name, on_mouse, param) -> None"},
-  {"Subdiv2DLocate", pycvSubdiv2DLocate, METH_VARARGS, "Subdiv2DLocate(subdiv, pt) -> (loc, where)"},
-  {"WaitKey", (PyCFunction)pycvWaitKey, METH_KEYWORDS, "WaitKey(delay=0) -> int"},
-
   //{"CalcOpticalFlowFarneback", (PyCFunction)pycvCalcOpticalFlowFarneback, METH_KEYWORDS, "CalcOpticalFlowFarneback(prev, next, flow, pyr_scale=0.5, levels=3, win_size=15, iterations=3, poly_n=7, poly_sigma=1.5, flags=0) -> None"},
   //{"_HOGComputeDescriptors", (PyCFunction)pycvHOGComputeDescriptors, METH_KEYWORDS, "_HOGComputeDescriptors(image, win_stride=block_stride, locations=None, padding=(0,0), win_size=(64,128), block_size=(16,16), block_stride=(8,8), cell_size=(8,8), nbins=9, gammaCorrection=true) -> list_of_descriptors"},
   //{"_HOGDetect", (PyCFunction)pycvHOGDetect, METH_KEYWORDS, "_HOGDetect(image, svm_classifier, win_stride=block_stride, locations=None, padding=(0,0), win_size=(64,128), block_size=(16,16), block_stride=(8,8), cell_size=(8,8), nbins=9, gammaCorrection=true) -> list_of_points"},
index 6095efe82d9c2d12a95839ec1ed9a35a81d7401f..9ac580e646787dc6233031c0d64b76945ad7885e 100644 (file)
@@ -19,6 +19,10 @@ for l in open("%s/api" % sys.argv[1]):
   if l[0] == '#':
     continue
   l = l.rstrip()
+  if (not l.startswith(' ')) and ('/' in l):
+    (l, flags) = l.split('/')
+  else:
+    flags = ""
   f = l.split()
   if len(f) != 0:
     if l[0] != ' ':
@@ -26,13 +30,13 @@ for l in open("%s/api" % sys.argv[1]):
         ty = f[1]
       else:
         ty = None
-      api.append((f[0], [], ty))
+      api.append((f[0], [], ty, flags))
     else:
       api[-1][1].append(argument(f))
 
 # Validation: check that any optional arguments are last
 had_error = False
-for (f, args, ty) in api:
+for (f, args, ty, flags) in api:
     if f == 'PolarToCart':
         print f, [(a.init != None) for a in args]
     has_init = [(a.init != None) for a in args if not 'O' in a.flags]
@@ -112,6 +116,8 @@ conversion_types = [
 'generic',
 'IplConvKernel*',
 'IplImage',
+'PyObject*',
+'PyCallableObject*'
 ]
 
 def safename(s):
@@ -121,185 +127,190 @@ def has_optional(al):
     """ return true if any argument is optional """
     return any([a.init for a in al])
 
-def gen(name, args, ty):
+def gen(name, args, ty, flags):
   yield ""
   if has_optional(args):
       yield "static PyObject *pycv%s(PyObject *self, PyObject *args, PyObject *kw)" % cname(name) 
   else:
       yield "static PyObject *pycv%s(PyObject *self, PyObject *args)" % cname(name)
-  yield "{"
-
-  destinations = []
-  for a in args:
-    remap = {
-     'CvArr' : 'CvArr*',
-     'CvMat' : 'CvMat*',
-     'CvMatND' : 'CvMatND*',
-     'IplImage' : 'IplImage*',
-     'CvMemStorage' : 'CvMemStorage*',
-     'CvHistogram':'CvHistogram*',
-     'CvSeq':'CvSeq*',
-     'CvHaarClassifierCascade' : 'CvHaarClassifierCascade*'
-    }
-    ctype = remap.get(a.ty, a.ty)
-    if a.init:
-      init = " = %s" % a.init
-    else:
-      init = ''
-    yield "  %s %s%s;" % (ctype, a.nm, init)
-    if 'O' in a.flags:
-      continue
-    if a.ty in (conversion_types + aggregate.keys()):
-      yield '  PyObject *pyobj_%s = NULL;' % (a.nm)
-      destinations.append('&pyobj_%s' % (a.nm))
-    elif a.ty in [ 'CvPoint2D32f' ]:
-      destinations.append('&%s.x, &%s.y' % (a.nm, a.nm))
-    elif a.ty in [ 'CvTermCriteria' ]:
-      destinations.append('&%s.type, &%s.max_iter, &%s.epsilon' % ((a.nm,)*3))
-    elif a.ty in [ 'CvSURFParams' ]:
-      destinations.append('&%s.extended, &%s.hessianThreshold, &%s.nOctaves, &%s.nOctaveLayers' % ((a.nm,)*4))
-    elif a.nm in [ 'CvBox2D' ]:
-      s = ", ".join([('&' + a.nm +'.' + fld) for fld in [ 'center.x', 'center.y', 'size.width', 'size.height', 'angle' ] ])
-      destinations.append(s)
-    else:
-      destinations.append('&%s' % a.nm)
-  fmap = {
-    'CvSURFParams' : '(idii)',
-    'double' : 'd',
-    'float' : 'f',
-    'int' : 'i',
-    'int64' : 'L',
-    'char*' : 's',
-  }
-  for k in (conversion_types + aggregate.keys()):
-    fmap[k] = 'O'
-  in_args = [ a for a in args if not 'O' in a.flags ]
-  fmt0 = "".join([ fmap[a.ty] for a in in_args if not a.init])
-  fmt1 = "".join([ fmap[a.ty] for a in in_args if a.init])
-      
-  yield ''
-  if len(fmt0 + fmt1) > 0:
-    if len(fmt1) > 0:
-      yield '  const char *keywords[] = { %s };' % (", ".join([ '"%s"' % arg.nm for arg in args if not 'O' in arg.flags ] + ['NULL']))
-      yield '  if (!PyArg_ParseTupleAndKeywords(args, kw, "%s|%s", %s))' % (fmt0, fmt1, ", ".join(['(char**)keywords'] + destinations))
-      if '(' in (fmt0 + fmt1):
-        print "Tuple with kwargs is not allowed, function", name
-        sys.exit(1)
-    else:
-      yield '  if (!PyArg_ParseTuple(args, "%s", %s))' % (fmt0, ", ".join(destinations))
-    yield '    return NULL;'
-
-  # Do the conversions:
-  for a in args:
-    joinwith = [f[2:] for f in a.flags if f.startswith("J:")]
-    if len(joinwith) > 0:
-      yield 'preShareData(%s, &%s);' % (joinwith[0], a.nm)
-    if 'O' in a.flags:
-      continue
-    if a.ty in (conversion_types + aggregate.keys()):
+  if 'doconly' in flags:
+    yield ";"
+  else:
+    yield "{"
+
+    destinations = []
+    for a in args:
+      remap = {
+       'CvArr' : 'CvArr*',
+       'CvMat' : 'CvMat*',
+       'CvMatND' : 'CvMatND*',
+       'IplImage' : 'IplImage*',
+       'CvMemStorage' : 'CvMemStorage*',
+       'CvHistogram':'CvHistogram*',
+       'CvSeq':'CvSeq*',
+       'CvHaarClassifierCascade' : 'CvHaarClassifierCascade*'
+      }
+      ctype = remap.get(a.ty, a.ty)
       if a.init:
-        pred = '(pyobj_%s != NULL) && ' % a.nm
+        init = " = %s" % a.init
       else:
-        pred = ''
-      yield '  if (%s!convert_to_%s(pyobj_%s, &%s, "%s")) return NULL;' % (pred, safename(a.ty), a.nm, a.nm, a.nm)
-
-  yield '#ifdef CVPY_VALIDATE_%s' % name
-  yield 'CVPY_VALIDATE_%s();' % name
-  yield '#endif'
-
-  def invokename(a):
-    if 'K' in a.flags:
-      prefix = "(const CvArr **)"
-    elif 'O' in a.flags and not 'A' in a.flags:
-      prefix = "&"
-    else:
-      prefix = ""
-    if a.ty in aggregate:
-      return prefix + aggregate[a.ty].replace('!', a.nm)
-    else:
-      return prefix + a.nm
+        init = ''
+      yield "  %s %s%s;" % (ctype, a.nm, init)
+      if 'O' in a.flags:
+        continue
+      if a.ty in (conversion_types + aggregate.keys()):
+        yield '  PyObject *pyobj_%s = NULL;' % (a.nm)
+        destinations.append('&pyobj_%s' % (a.nm))
+      elif a.ty in [ 'CvPoint2D32f' ]:
+        destinations.append('&%s.x, &%s.y' % (a.nm, a.nm))
+      elif a.ty in [ 'CvTermCriteria' ]:
+        destinations.append('&%s.type, &%s.max_iter, &%s.epsilon' % ((a.nm,)*3))
+      elif a.ty in [ 'CvSURFParams' ]:
+        destinations.append('&%s.extended, &%s.hessianThreshold, &%s.nOctaves, &%s.nOctaveLayers' % ((a.nm,)*4))
+      elif a.nm in [ 'CvBox2D' ]:
+        s = ", ".join([('&' + a.nm +'.' + fld) for fld in [ 'center.x', 'center.y', 'size.width', 'size.height', 'angle' ] ])
+        destinations.append(s)
+      else:
+        destinations.append('&%s' % a.nm)
+    fmap = {
+      'CvSURFParams' : '(idii)',
+      'double' : 'd',
+      'float' : 'f',
+      'int' : 'i',
+      'int64' : 'L',
+      'char*' : 's',
+    }
+    for k in (conversion_types + aggregate.keys()):
+      fmap[k] = 'O'
+    in_args = [ a for a in args if not 'O' in a.flags ]
+    fmt0 = "".join([ fmap[a.ty] for a in in_args if not a.init])
+    fmt1 = "".join([ fmap[a.ty] for a in in_args if a.init])
+        
+    yield ''
+    if len(fmt0 + fmt1) > 0:
+      if len(fmt1) > 0:
+        yield '  const char *keywords[] = { %s };' % (", ".join([ '"%s"' % arg.nm for arg in args if not 'O' in arg.flags ] + ['NULL']))
+        yield '  if (!PyArg_ParseTupleAndKeywords(args, kw, "%s|%s", %s))' % (fmt0, fmt1, ", ".join(['(char**)keywords'] + destinations))
+        if '(' in (fmt0 + fmt1):
+          print "Tuple with kwargs is not allowed, function", name
+          sys.exit(1)
+      else:
+        yield '  if (!PyArg_ParseTuple(args, "%s", %s))' % (fmt0, ", ".join(destinations))
+      yield '    return NULL;'
+
+    # Do the conversions:
+    for a in args:
+      joinwith = [f[2:] for f in a.flags if f.startswith("J:")]
+      if len(joinwith) > 0:
+        yield 'preShareData(%s, &%s);' % (joinwith[0], a.nm)
+      if 'O' in a.flags:
+        continue
+      if a.ty in (conversion_types + aggregate.keys()):
+        if a.init:
+          pred = '(pyobj_%s != NULL) && ' % a.nm
+        else:
+          pred = ''
+        yield '  if (%s!convert_to_%s(pyobj_%s, &%s, "%s")) return NULL;' % (pred, safename(a.ty), a.nm, a.nm, a.nm)
+
+    yield '#ifdef CVPY_VALIDATE_%s' % name
+    yield 'CVPY_VALIDATE_%s();' % name
+    yield '#endif'
+
+    def invokename(a):
+      if 'K' in a.flags:
+        prefix = "(const CvArr **)"
+      elif 'O' in a.flags and not 'A' in a.flags:
+        prefix = "&"
+      else:
+        prefix = ""
+      if a.ty in aggregate:
+        return prefix + aggregate[a.ty].replace('!', a.nm)
+      else:
+        return prefix + a.nm
 
-  def funcname(s):
-    # The name by which the function is called, in C
-    if s.startswith("CV"):
-      return s
-    else:
-      return "cv" + s
-  tocall = '%s(%s)' % (funcname(name), ", ".join(invokename(a) for a in args))
-  if ty == None:
-    yield '  ERRWRAP(%s);' % tocall
-    yield '  Py_RETURN_NONE;'
-  else:
-    Rtypes = [
-      'int',
-      'int64',
-      'double',
-      'CvCapture*',
-      'CvVideoWriter*',
-      'CvPOSITObject*',
-      'CvScalar',
-      'CvSize',
-      'CvRect',
-      'CvSeq*',
-      'CvBox2D',
-      'CvSeqOfCvAvgComp*',
-      'CvSeqOfCvConvexityDefect*',
-      'CvSeqOfCvStarKeypoint*',
-      'CvSeqOfCvSURFPoint*',
-      'CvSeqOfCvSURFDescriptor*',
-      'CvContourTree*',
-      'IplConvKernel*',
-      'IplImage*',
-      'CvMat*',
-      'constCvMat*',
-      'ROCvMat*',
-      'CvMatND*',
-      'CvPoint2D32f_4',
-      'CvRNG',
-      'CvSubdiv2D*',
-      'CvSubdiv2DPoint*',
-      'CvSubdiv2DEdge',
-      'ROIplImage*',
-      'CvStereoBMState*',
-      'CvStereoGCState*',
-      'CvKalman*',
-      'float',
-      'generic',
-      'unsigned' ]
-
-    if ty in Rtypes:
-      yield '  %s r;' % (ty)
-      yield '  ERRWRAP(r = %s);' % (tocall)
-      yield '  return FROM_%s(r);' % safename(ty)
+    def funcname(s):
+      # The name by which the function is called, in C
+      if s.startswith("CV"):
+        return s
+      else:
+        return "cv" + s
+    tocall = '%s(%s)' % (funcname(name), ", ".join(invokename(a) for a in args))
+    if 'stub' in flags:
+      yield '  return stub%s(%s);' % (name, ", ".join(invokename(a) for a in args))
+    elif ty == None:
+      yield '  ERRWRAP(%s);' % tocall
+      yield '  Py_RETURN_NONE;'
     else:
-      all_returns = ty.split(",")
-      return_value_from_call = len(set(Rtypes) & set(all_returns)) != 0
-      if return_value_from_call:
-        yield '  %s r;' % list(set(Rtypes) & set(all_returns))[0]
+      Rtypes = [
+        'int',
+        'int64',
+        'double',
+        'CvCapture*',
+        'CvVideoWriter*',
+        'CvPOSITObject*',
+        'CvScalar',
+        'CvSize',
+        'CvRect',
+        'CvSeq*',
+        'CvBox2D',
+        'CvSeqOfCvAvgComp*',
+        'CvSeqOfCvConvexityDefect*',
+        'CvSeqOfCvStarKeypoint*',
+        'CvSeqOfCvSURFPoint*',
+        'CvSeqOfCvSURFDescriptor*',
+        'CvContourTree*',
+        'IplConvKernel*',
+        'IplImage*',
+        'CvMat*',
+        'constCvMat*',
+        'ROCvMat*',
+        'CvMatND*',
+        'CvPoint2D32f_4',
+        'CvRNG',
+        'CvSubdiv2D*',
+        'CvSubdiv2DPoint*',
+        'CvSubdiv2DEdge',
+        'ROIplImage*',
+        'CvStereoBMState*',
+        'CvStereoGCState*',
+        'CvKalman*',
+        'float',
+        'generic',
+        'unsigned' ]
+
+      if ty in Rtypes:
+        yield '  %s r;' % (ty)
         yield '  ERRWRAP(r = %s);' % (tocall)
+        yield '  return FROM_%s(r);' % safename(ty)
       else:
-        yield '  ERRWRAP(%s);' % (tocall)
-      typed = dict([ (a.nm,a.ty) for a in args])
-      for i in range(len(all_returns)):
-        if all_returns[i] in Rtypes:
-          typed['r'] = all_returns[i]
-          all_returns[i] = "r"
-      if len(all_returns) == 1:
-        af = dict([ (a.nm,a.flags) for a in args])
-        joinwith = [f[2:] for f in af.get(all_returns[0], []) if f.startswith("J:")]
-        if len(joinwith) > 0:
-            yield '  return shareData(pyobj_%s, %s, %s);' % (joinwith[0], joinwith[0], all_returns[0])
+        all_returns = ty.split(",")
+        return_value_from_call = len(set(Rtypes) & set(all_returns)) != 0
+        if return_value_from_call:
+          yield '  %s r;' % list(set(Rtypes) & set(all_returns))[0]
+          yield '  ERRWRAP(r = %s);' % (tocall)
         else:
-            yield '  return FROM_%s(%s);' % (safename(typed[all_returns[0]]), all_returns[0])
-      else:
-        yield '  return Py_BuildValue("%s", %s);' % ("N" * len(all_returns), ", ".join(["FROM_%s(%s)" % (safename(typed[n]), n) for n in all_returns]))
+          yield '  ERRWRAP(%s);' % (tocall)
+        typed = dict([ (a.nm,a.ty) for a in args])
+        for i in range(len(all_returns)):
+          if all_returns[i] in Rtypes:
+            typed['r'] = all_returns[i]
+            all_returns[i] = "r"
+        if len(all_returns) == 1:
+          af = dict([ (a.nm,a.flags) for a in args])
+          joinwith = [f[2:] for f in af.get(all_returns[0], []) if f.startswith("J:")]
+          if len(joinwith) > 0:
+              yield '  return shareData(pyobj_%s, %s, %s);' % (joinwith[0], joinwith[0], all_returns[0])
+          else:
+              yield '  return FROM_%s(%s);' % (safename(typed[all_returns[0]]), all_returns[0])
+        else:
+          yield '  return Py_BuildValue("%s", %s);' % ("N" * len(all_returns), ", ".join(["FROM_%s(%s)" % (safename(typed[n]), n) for n in all_returns]))
 
-  yield '}'
+    yield '}'
 
 gen_c = [ open("generated%d.i" % i, "w") for i in range(5) ]
 
 print "Generated %d functions" % len(api)
-for nm,args,ty in sorted(api):
+for nm,args,ty,flags in sorted(api):
 
   # Figure out docstring into ds_*
   ds_args = []
@@ -323,7 +334,7 @@ for nm,args,ty in sorted(api):
   print >>gen_c[1], entry % (nm)
   if nm.startswith('CV_'):
     print >>gen_c[1], entry % (nm[3:])
-  for l in gen(nm,args,ty):
+  for l in gen(nm,args,ty,flags):
     print >>gen_c[0], l
 
 for l in open("%s/defs" % sys.argv[1]):