[{"data":1,"prerenderedAt":1466},["ShallowReactive",2],{"doc:\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fread-pyqgis-api-docs-cpp-signatures":3},{"id":4,"title":5,"body":6,"description":1455,"extension":1456,"meta":1457,"navigation":205,"path":1462,"seo":1463,"stem":1464,"__hash__":1465},"docs\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fread-pyqgis-api-docs-cpp-signatures\u002Findex.md","Read the PyQGIS API Docs and C++ Signatures",{"type":7,"value":8,"toc":1441},"minimark",[9,13,29,38,151,156,166,170,173,343,405,409,419,533,555,559,569,627,756,771,775,794,874,952,975,979,982,1051,1060,1064,1067,1278,1298,1302,1310,1314,1347,1351,1364,1368,1374,1384,1397,1406,1410,1437],[10,11,5],"h1",{"id":12},"read-the-pyqgis-api-docs-and-c-signatures",[14,15,16,17,21,22,21,25,28],"p",{},"QGIS is written in C++, and Python reaches it through generated bindings. The PyQGIS documentation is generated from the same sources, so method signatures, types and notes are written with C++ in mind — ",[18,19,20],"code",{},"const QgsFeatureRequest &request = QgsFeatureRequest()",", ",[18,23,24],{},"bool *ok = nullptr",[18,26,27],{},"QgsVectorLayer::EditResult",". Once you know how a handful of C++ conventions map to Python, the documentation becomes the fastest way to answer \"what can this class do?\" — faster than searching for examples that may be outdated.",[14,30,31,32,37],{},"This recipe belongs to ",[33,34,36],"a",{"href":35},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002F","QGIS API Architecture",". It explains how to read a signature, how pointers, references and const translate, how out-parameters become returned tuples, how enums and flags are written in Python, how signals appear, and where Python-specific notes hide.",[14,39,40],{},[41,42,47,51,55,62,79,88,97,103,108,112,116,120,127,133,138,141,144,148],"svg",{"viewBox":43,"role":44,"ariaLabel":45,"xmlns":46},"0 0 760 280","img","Mapping a C++ signature with const references and defaults to a Python call, and out-parameters to returned tuples","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg",[48,49,50],"title",{},"From a C++ signature to a Python call",[52,53,54],"desc",{},"A C++ signature such as QgsFeatureIterator getFeatures(const QgsFeatureRequest &request = QgsFeatureRequest()) const maps to the Python call layer.getFeatures(request), with the default making the argument optional. A signature with an out-parameter, such as double measureLine(const QgsPointXY &p1, const QgsPointXY &p2) returning extra values through pointers, becomes a call that returns a tuple. Const and references disappear in Python.",[56,57],"rect",{"x":58,"y":58,"width":59,"height":60,"fill":61},"0","760","280","#f6f3ea",[63,64,65],"defs",{},[66,67,74],"marker",{"id":68,"viewBox":69,"refX":70,"refY":71,"markerWidth":72,"markerHeight":72,"orient":73},"apiMapArrow","0 0 10 10","8","5","7","auto-start-reverse",[75,76],"path",{"d":77,"fill":78},"M0 0 L10 5 L0 10 z","#2f3b35",[80,81,87],"text",{"x":82,"y":83,"style":84,"fill":85,"textAnchor":86},"380","28","text-anchor:middle;font-size:14px;font-family:sans-serif;font-weight:bold","#17211d","middle","What survives the translation",[56,89],{"x":90,"y":91,"width":92,"height":93,"rx":70,"fill":94,"stroke":95,"style":96},"24","52","340","196","#fffdf7","#59645f","stroke-width:2",[80,98,102],{"x":99,"y":100,"style":101,"fill":85,"textAnchor":86},"194","97.6","text-anchor:middle;font-size:11.0px;font-family:sans-serif;font-weight:bold","C++ signature",[80,104,107],{"x":99,"y":105,"style":106,"fill":78,"textAnchor":86},"125.6","text-anchor:middle;font-size:9.5px;font-family:monospace","QgsFeatureIterator",[80,109,111],{"x":99,"y":110,"style":106,"fill":78,"textAnchor":86},"153.6","getFeatures(const",[80,113,115],{"x":99,"y":114,"style":106,"fill":78,"textAnchor":86},"181.6","QgsFeatureRequest &request",[80,117,119],{"x":99,"y":118,"style":106,"fill":78,"textAnchor":86},"209.6","= QgsFeatureRequest()) const",[121,122],"line",{"x1":123,"y1":124,"x2":125,"y2":124,"stroke":78,"style":126},"364","150","396","stroke-width:1.8;marker-end:url(#apiMapArrow)",[56,128],{"x":129,"y":91,"width":130,"height":93,"rx":70,"fill":131,"stroke":132,"style":96},"400","336","#e8efe6","#15803d",[80,134,137],{"x":135,"y":100,"style":101,"fill":136,"textAnchor":86},"568","#166534","Python",[80,139,140],{"x":135,"y":105,"style":106,"fill":78,"textAnchor":86},"it = layer.getFeatures(req)",[80,142,143],{"x":135,"y":110,"style":106,"fill":78,"textAnchor":86},"it = layer.getFeatures()",[80,145,147],{"x":135,"y":114,"style":146,"fill":95,"textAnchor":86},"text-anchor:middle;font-size:10.0px;font-family:sans-serif","const, & and * vanish",[80,149,150],{"x":135,"y":118,"style":146,"fill":95,"textAnchor":86},"defaults → optional args",[152,153,155],"h2",{"id":154},"prerequisites","Prerequisites",[157,158,159,163],"ul",{},[160,161,162],"li",{},"Access to the PyQGIS API reference for your version (qgis.org\u002Fpyqgis\u002F) and, when needed, the C++ reference (api.qgis.org), which often has fuller descriptions.",[160,164,165],{},"A Python console to try calls as you read.",[152,167,169],{"id":168},"read-a-method-signature","Read a method signature",[14,171,172],{},"Every method entry gives a return type, a name, typed parameters with optional defaults, and qualifiers. Most of it maps directly to Python.",[174,175,180],"pre",{"className":176,"code":177,"language":178,"meta":179,"style":179},"language-python shiki shiki-themes github-dark","from qgis.core import QgsProject, QgsFeatureRequest\n\nlayer = QgsProject.instance().mapLayersByName(\"districts\")[0]\n\n# C++: QgsFeatureIterator getFeatures(const QgsFeatureRequest &request = QgsFeatureRequest()) const\nit_all = layer.getFeatures()                                    # default argument used\nit_some = layer.getFeatures(QgsFeatureRequest().setLimit(5))    # explicit argument\n\n# C++: QgsFeature getFeature(QgsFeatureId fid) const\nf = layer.getFeature(3)\nprint(type(it_all).__name__, f.isValid())\n\nhelp(layer.getFeatures)          # the docstring shows the Python signature\n","python","",[18,181,182,200,207,232,237,244,258,277,282,288,305,326,331],{"__ignoreMap":179},[183,184,186,190,194,197],"span",{"class":121,"line":185},1,[183,187,189],{"class":188},"snl16","from",[183,191,193],{"class":192},"s95oV"," qgis.core ",[183,195,196],{"class":188},"import",[183,198,199],{"class":192}," QgsProject, QgsFeatureRequest\n",[183,201,203],{"class":121,"line":202},2,[183,204,206],{"emptyLinePlaceholder":205},true,"\n",[183,208,210,213,216,219,223,226,229],{"class":121,"line":209},3,[183,211,212],{"class":192},"layer ",[183,214,215],{"class":188},"=",[183,217,218],{"class":192}," QgsProject.instance().mapLayersByName(",[183,220,222],{"class":221},"sU2Wk","\"districts\"",[183,224,225],{"class":192},")[",[183,227,58],{"class":228},"sDLfK",[183,230,231],{"class":192},"]\n",[183,233,235],{"class":121,"line":234},4,[183,236,206],{"emptyLinePlaceholder":205},[183,238,240],{"class":121,"line":239},5,[183,241,243],{"class":242},"sjoCn","# C++: QgsFeatureIterator getFeatures(const QgsFeatureRequest &request = QgsFeatureRequest()) const\n",[183,245,247,250,252,255],{"class":121,"line":246},6,[183,248,249],{"class":192},"it_all ",[183,251,215],{"class":188},[183,253,254],{"class":192}," layer.getFeatures()                                    ",[183,256,257],{"class":242},"# default argument used\n",[183,259,261,264,266,269,271,274],{"class":121,"line":260},7,[183,262,263],{"class":192},"it_some ",[183,265,215],{"class":188},[183,267,268],{"class":192}," layer.getFeatures(QgsFeatureRequest().setLimit(",[183,270,71],{"class":228},[183,272,273],{"class":192},"))    ",[183,275,276],{"class":242},"# explicit argument\n",[183,278,280],{"class":121,"line":279},8,[183,281,206],{"emptyLinePlaceholder":205},[183,283,285],{"class":121,"line":284},9,[183,286,287],{"class":242},"# C++: QgsFeature getFeature(QgsFeatureId fid) const\n",[183,289,291,294,296,299,302],{"class":121,"line":290},10,[183,292,293],{"class":192},"f ",[183,295,215],{"class":188},[183,297,298],{"class":192}," layer.getFeature(",[183,300,301],{"class":228},"3",[183,303,304],{"class":192},")\n",[183,306,308,311,314,317,320,323],{"class":121,"line":307},11,[183,309,310],{"class":228},"print",[183,312,313],{"class":192},"(",[183,315,316],{"class":228},"type",[183,318,319],{"class":192},"(it_all).",[183,321,322],{"class":228},"__name__",[183,324,325],{"class":192},", f.isValid())\n",[183,327,329],{"class":121,"line":328},12,[183,330,206],{"emptyLinePlaceholder":205},[183,332,334,337,340],{"class":121,"line":333},13,[183,335,336],{"class":228},"help",[183,338,339],{"class":192},"(layer.getFeatures)          ",[183,341,342],{"class":242},"# the docstring shows the Python signature\n",[14,344,345,349,350,21,353,356,357,360,361,364,365,368,369,21,372,368,375,21,378,356,381,384,385,21,387,368,390,21,392,368,395,397,398,400,401,404],{},[346,347,348],"strong",{},"Breakdown:"," ",[18,351,352],{},"const",[18,354,355],{},"&"," and ",[18,358,359],{},"*"," describe how C++ passes and protects values; in Python they disappear — you pass the object. Parameters with ",[18,362,363],{},"= default"," become optional. Type names map to Python classes of the same name, and simple types map to Python types: ",[18,366,367],{},"QString"," is ",[18,370,371],{},"str",[18,373,374],{},"double",[18,376,377],{},"float",[18,379,380],{},"int",[18,382,383],{},"qint64"," are ",[18,386,380],{},[18,388,389],{},"bool",[18,391,389],{},[18,393,394],{},"QgsFeatureId",[18,396,380],{},". A trailing ",[18,399,352],{}," on the method means it does not modify the object. ",[18,402,403],{},"help()"," on a bound method prints the docstring generated from the same documentation, which is often quicker than the website for a quick check.",[152,406,408],{"id":407},"pointers-ownership-and-transfers-ownership","Pointers, ownership and \"transfers ownership\"",[14,410,411,412,21,415,418],{},"Pointers in signatures — ",[18,413,414],{},"QgsVectorLayer *layer",[18,416,417],{},"QgsSymbol *symbol"," — mean the object is passed by address. The documentation's ownership notes then matter: they say who deletes the object later.",[174,420,422],{"className":176,"code":421,"language":178,"meta":179,"style":179},"from qgis.core import QgsMarkerSymbol, QgsSingleSymbolRenderer\n\n# C++: QgsSingleSymbolRenderer(QgsSymbol *symbol SIP_TRANSFER)\nsymbol = QgsMarkerSymbol.createSimple({\"color\": \"#2563eb\"})\nrenderer = QgsSingleSymbolRenderer(symbol)      # renderer now owns symbol\n\n# C++: void setRenderer(QgsFeatureRenderer *r SIP_TRANSFER)\nlayer_pts = QgsProject.instance().mapLayersByName(\"stations\")[0]\nlayer_pts.setRenderer(renderer)                 # layer now owns renderer\n\n# do not reuse `symbol` for another renderer; clone it instead\nother = QgsSingleSymbolRenderer(symbol.clone())\n",[18,423,424,435,439,444,466,479,483,488,506,514,518,523],{"__ignoreMap":179},[183,425,426,428,430,432],{"class":121,"line":185},[183,427,189],{"class":188},[183,429,193],{"class":192},[183,431,196],{"class":188},[183,433,434],{"class":192}," QgsMarkerSymbol, QgsSingleSymbolRenderer\n",[183,436,437],{"class":121,"line":202},[183,438,206],{"emptyLinePlaceholder":205},[183,440,441],{"class":121,"line":209},[183,442,443],{"class":242},"# C++: QgsSingleSymbolRenderer(QgsSymbol *symbol SIP_TRANSFER)\n",[183,445,446,449,451,454,457,460,463],{"class":121,"line":234},[183,447,448],{"class":192},"symbol ",[183,450,215],{"class":188},[183,452,453],{"class":192}," QgsMarkerSymbol.createSimple({",[183,455,456],{"class":221},"\"color\"",[183,458,459],{"class":192},": ",[183,461,462],{"class":221},"\"#2563eb\"",[183,464,465],{"class":192},"})\n",[183,467,468,471,473,476],{"class":121,"line":239},[183,469,470],{"class":192},"renderer ",[183,472,215],{"class":188},[183,474,475],{"class":192}," QgsSingleSymbolRenderer(symbol)      ",[183,477,478],{"class":242},"# renderer now owns symbol\n",[183,480,481],{"class":121,"line":246},[183,482,206],{"emptyLinePlaceholder":205},[183,484,485],{"class":121,"line":260},[183,486,487],{"class":242},"# C++: void setRenderer(QgsFeatureRenderer *r SIP_TRANSFER)\n",[183,489,490,493,495,497,500,502,504],{"class":121,"line":279},[183,491,492],{"class":192},"layer_pts ",[183,494,215],{"class":188},[183,496,218],{"class":192},[183,498,499],{"class":221},"\"stations\"",[183,501,225],{"class":192},[183,503,58],{"class":228},[183,505,231],{"class":192},[183,507,508,511],{"class":121,"line":284},[183,509,510],{"class":192},"layer_pts.setRenderer(renderer)                 ",[183,512,513],{"class":242},"# layer now owns renderer\n",[183,515,516],{"class":121,"line":290},[183,517,206],{"emptyLinePlaceholder":205},[183,519,520],{"class":121,"line":307},[183,521,522],{"class":242},"# do not reuse `symbol` for another renderer; clone it instead\n",[183,524,525,528,530],{"class":121,"line":328},[183,526,527],{"class":192},"other ",[183,529,215],{"class":188},[183,531,532],{"class":192}," QgsSingleSymbolRenderer(symbol.clone())\n",[14,534,535,537,538,541,542,545,546,549,550,554],{},[346,536,348],{}," \"Ownership of … is transferred\" (shown as ",[18,539,540],{},"SIP_TRANSFER"," in sources) means the receiving object will delete it; after the call, the Python variable still refers to the object but you must not give it to anything else, or two owners will try to delete it — a classic crash. ",[18,543,544],{},"clone()"," makes an independent copy for reuse. Return values marked as \"caller takes ownership\" (",[18,547,548],{},"SIP_FACTORY",") are yours to keep. The full picture of ownership and its crashes is in ",[33,551,553],{"href":552},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fqgis-object-ownership-and-crashes-pyqgis\u002F","object ownership and crashes",".",[152,556,558],{"id":557},"out-parameters-become-returned-tuples","Out-parameters become returned tuples",[14,560,561,562,21,565,568],{},"C++ methods often return extra values through pointer or reference parameters: ",[18,563,564],{},"bool *ok",[18,566,567],{},"QString &error",". In Python those parameters disappear from the call, and the values come back as a tuple.",[14,570,571],{},[41,572,575,578,581,584,591,594,598,601,604,607,610,614,616,618,621,624],{"viewBox":573,"role":44,"ariaLabel":574,"xmlns":46},"0 0 760 240","A C++ method with out-parameters returning a tuple in Python, with the return value first and out-parameters after",[48,576,577],{},"Out-parameters in Python",[52,579,580],{},"A C++ method with a return value and an out-parameter, such as bool exportLayer(..., QString *errorMessage), becomes a Python call that returns a tuple of the return value followed by each out-parameter in order. The Python docstring shows the tuple shape. Unpacking the tuple gives both values.",[56,582],{"x":58,"y":58,"width":59,"height":583,"fill":61},"240",[63,585,586],{},[66,587,589],{"id":588,"viewBox":69,"refX":70,"refY":71,"markerWidth":72,"markerHeight":72,"orient":73},"apiTupleArrow",[75,590],{"d":77,"fill":78},[80,592,593],{"x":82,"y":83,"style":84,"fill":85,"textAnchor":86},"Return value first, then the outs",[56,595],{"x":90,"y":596,"width":92,"height":597,"rx":70,"fill":94,"stroke":95,"style":96},"56","160",[80,599,600],{"x":99,"y":100,"style":101,"fill":85,"textAnchor":86},"C++",[80,602,603],{"x":99,"y":105,"style":106,"fill":78,"textAnchor":86},"T method(…, X *out1,",[80,605,606],{"x":99,"y":110,"style":106,"fill":78,"textAnchor":86},"           Y &out2)",[80,608,609],{"x":99,"y":114,"style":146,"fill":95,"textAnchor":86},"extra results via pointers",[121,611],{"x1":123,"y1":612,"x2":125,"y2":612,"stroke":78,"style":613},"136","stroke-width:1.8;marker-end:url(#apiTupleArrow)",[56,615],{"x":129,"y":596,"width":130,"height":597,"rx":70,"fill":131,"stroke":132,"style":96},[80,617,137],{"x":135,"y":100,"style":101,"fill":136,"textAnchor":86},[80,619,620],{"x":135,"y":105,"style":106,"fill":78,"textAnchor":86},"result, out1, out2 =",[80,622,623],{"x":135,"y":110,"style":106,"fill":78,"textAnchor":86},"    obj.method(…)",[80,625,626],{"x":135,"y":114,"style":146,"fill":95,"textAnchor":86},"see the docstring",[174,628,630],{"className":176,"code":629,"language":178,"meta":179,"style":179},"from qgis.core import QgsExpression\n\n# C++: static bool checkExpression(const QString &text, const QgsExpressionContext *context,\n#                                  QString &errorMessage)\nok, message = QgsExpression.checkExpression('\"name\" ||', None)\nprint(ok, message)\n\nfrom qgis.core import QgsGeometry, QgsPointXY\n\n# C++: double closestSegmentWithContext(const QgsPointXY &point, QgsPointXY &minDistPoint,\n#          int &nextVertexIndex, int *leftOf = nullptr, double epsilon = ...) const\nline = QgsGeometry.fromWkt(\"LineString (0 0, 10 0)\")\nsqr_dist, nearest, next_vertex, left_of = line.closestSegmentWithContext(QgsPointXY(3, 2))\nprint(sqr_dist, nearest, next_vertex, left_of)\n",[18,631,632,643,647,652,657,677,684,688,699,703,708,713,728,748],{"__ignoreMap":179},[183,633,634,636,638,640],{"class":121,"line":185},[183,635,189],{"class":188},[183,637,193],{"class":192},[183,639,196],{"class":188},[183,641,642],{"class":192}," QgsExpression\n",[183,644,645],{"class":121,"line":202},[183,646,206],{"emptyLinePlaceholder":205},[183,648,649],{"class":121,"line":209},[183,650,651],{"class":242},"# C++: static bool checkExpression(const QString &text, const QgsExpressionContext *context,\n",[183,653,654],{"class":121,"line":234},[183,655,656],{"class":242},"#                                  QString &errorMessage)\n",[183,658,659,662,664,667,670,672,675],{"class":121,"line":239},[183,660,661],{"class":192},"ok, message ",[183,663,215],{"class":188},[183,665,666],{"class":192}," QgsExpression.checkExpression(",[183,668,669],{"class":221},"'\"name\" ||'",[183,671,21],{"class":192},[183,673,674],{"class":228},"None",[183,676,304],{"class":192},[183,678,679,681],{"class":121,"line":246},[183,680,310],{"class":228},[183,682,683],{"class":192},"(ok, message)\n",[183,685,686],{"class":121,"line":260},[183,687,206],{"emptyLinePlaceholder":205},[183,689,690,692,694,696],{"class":121,"line":279},[183,691,189],{"class":188},[183,693,193],{"class":192},[183,695,196],{"class":188},[183,697,698],{"class":192}," QgsGeometry, QgsPointXY\n",[183,700,701],{"class":121,"line":284},[183,702,206],{"emptyLinePlaceholder":205},[183,704,705],{"class":121,"line":290},[183,706,707],{"class":242},"# C++: double closestSegmentWithContext(const QgsPointXY &point, QgsPointXY &minDistPoint,\n",[183,709,710],{"class":121,"line":307},[183,711,712],{"class":242},"#          int &nextVertexIndex, int *leftOf = nullptr, double epsilon = ...) const\n",[183,714,715,718,720,723,726],{"class":121,"line":328},[183,716,717],{"class":192},"line ",[183,719,215],{"class":188},[183,721,722],{"class":192}," QgsGeometry.fromWkt(",[183,724,725],{"class":221},"\"LineString (0 0, 10 0)\"",[183,727,304],{"class":192},[183,729,730,733,735,738,740,742,745],{"class":121,"line":333},[183,731,732],{"class":192},"sqr_dist, nearest, next_vertex, left_of ",[183,734,215],{"class":188},[183,736,737],{"class":192}," line.closestSegmentWithContext(QgsPointXY(",[183,739,301],{"class":228},[183,741,21],{"class":192},[183,743,744],{"class":228},"2",[183,746,747],{"class":192},"))\n",[183,749,751,753],{"class":121,"line":750},14,[183,752,310],{"class":228},[183,754,755],{"class":192},"(sqr_dist, nearest, next_vertex, left_of)\n",[14,757,758,349,760,763,764,767,768,770],{},[346,759,348],{},[18,761,762],{},"checkExpression"," returns its boolean result first, then the error message the C++ version writes into its reference parameter. ",[18,765,766],{},"closestSegmentWithContext"," shows the same rule with several outs: the squared distance it returns, then the nearest point, the index of the next vertex and the side of the line, all of which C++ writes into reference and pointer parameters. The pattern is consistent across the API: return value first, then out-parameters in order. When a method has no return value but has out-parameters, Python returns just the out-parameters. The Python docstring — from ",[18,769,403],{}," or the PyQGIS reference — shows the tuple shape explicitly, so read it rather than guessing from the C++ signature.",[152,772,774],{"id":773},"enums-and-flags","Enums and flags",[14,776,777,778,21,781,21,784,786,787,790,791,793],{},"Enums appear in the docs as ",[18,779,780],{},"QgsWkbTypes::Type",[18,782,783],{},"Qgis::GeometryType",[18,785,27],{},". In Python, ",[18,788,789],{},"::"," becomes ",[18,792,554],{},", and recent releases use scoped names.",[14,795,796],{},[41,797,800,803,806,808,815,818,823,828,832,836,841,847,851,854,856,860,864,868,871],{"viewBox":798,"role":44,"ariaLabel":799,"xmlns":46},"0 0 760 196","An enum value's names across versions, from the old unscoped class member to the scoped Qgis form that works on QGIS 3 and QGIS 4",[48,801,802],{},"Enum names across versions",[52,804,805],{},"An enum documented as QgsWkbTypes::PolygonGeometry in older releases is written QgsWkbTypes.PolygonGeometry in Python on QGIS 3. After moving to the Qgis class it becomes Qgis.GeometryType.Polygon, the scoped form required by QGIS 4 and accepted by recent QGIS 3 releases. Writing the scoped form keeps code working on both.",[56,807],{"x":58,"y":58,"width":59,"height":93,"fill":61},[63,809,810],{},[66,811,813],{"id":812,"viewBox":69,"refX":70,"refY":71,"markerWidth":72,"markerHeight":72,"orient":73},"apiEnumsArrow",[75,814],{"d":77,"fill":78},[80,816,817],{"x":82,"y":83,"style":84,"fill":85,"textAnchor":86},"Write the scoped form, run on both",[56,819],{"x":90,"y":820,"width":821,"height":822,"rx":70,"fill":94,"stroke":95,"style":96},"60","222","120",[80,824,827],{"x":825,"y":826,"style":101,"fill":85,"textAnchor":86},"135","99.6","C++ docs",[80,829,831],{"x":825,"y":830,"style":106,"fill":78,"textAnchor":86},"123.6","QgsWkbTypes::",[80,833,835],{"x":825,"y":834,"style":106,"fill":78,"textAnchor":86},"147.6","PolygonGeometry",[121,837],{"x1":838,"y1":822,"x2":839,"y2":822,"stroke":78,"style":840},"246","288","stroke-width:1.8;marker-end:url(#apiEnumsArrow)",[56,842],{"x":843,"y":820,"width":844,"height":822,"rx":70,"fill":845,"stroke":846,"style":96},"292","200","#fdf2e2","#b45309",[80,848,850],{"x":849,"y":826,"style":101,"fill":846,"textAnchor":86},"392","old Python",[80,852,853],{"x":849,"y":830,"style":106,"fill":78,"textAnchor":86},"QgsWkbTypes.",[80,855,835],{"x":849,"y":834,"style":106,"fill":78,"textAnchor":86},[121,857],{"x1":858,"y1":822,"x2":859,"y2":822,"stroke":78,"style":840},"492","534",[56,861],{"x":862,"y":820,"width":863,"height":822,"rx":70,"fill":131,"stroke":132,"style":96},"538","198",[80,865,867],{"x":866,"y":826,"style":101,"fill":136,"textAnchor":86},"637","scoped",[80,869,870],{"x":866,"y":830,"style":106,"fill":78,"textAnchor":86},"Qgis.GeometryType",[80,872,873],{"x":866,"y":834,"style":106,"fill":78,"textAnchor":86},".Polygon",[174,875,877],{"className":176,"code":876,"language":178,"meta":179,"style":179},"from qgis.core import Qgis, QgsWkbTypes, QgsMapLayer\n\nprint(Qgis.GeometryType.Polygon)                      # scoped enum (QGIS 3.30+ and QGIS 4)\nprint(QgsWkbTypes.displayString(Qgis.WkbType.MultiPolygon))\n\n# flags combine with |\ncategories = QgsMapLayer.StyleCategory.Symbology | QgsMapLayer.StyleCategory.Labeling\nprint(bool(categories & QgsMapLayer.StyleCategory.Labeling))\n",[18,878,879,890,894,904,911,915,920,936],{"__ignoreMap":179},[183,880,881,883,885,887],{"class":121,"line":185},[183,882,189],{"class":188},[183,884,193],{"class":192},[183,886,196],{"class":188},[183,888,889],{"class":192}," Qgis, QgsWkbTypes, QgsMapLayer\n",[183,891,892],{"class":121,"line":202},[183,893,206],{"emptyLinePlaceholder":205},[183,895,896,898,901],{"class":121,"line":209},[183,897,310],{"class":228},[183,899,900],{"class":192},"(Qgis.GeometryType.Polygon)                      ",[183,902,903],{"class":242},"# scoped enum (QGIS 3.30+ and QGIS 4)\n",[183,905,906,908],{"class":121,"line":234},[183,907,310],{"class":228},[183,909,910],{"class":192},"(QgsWkbTypes.displayString(Qgis.WkbType.MultiPolygon))\n",[183,912,913],{"class":121,"line":239},[183,914,206],{"emptyLinePlaceholder":205},[183,916,917],{"class":121,"line":246},[183,918,919],{"class":242},"# flags combine with |\n",[183,921,922,925,927,930,933],{"class":121,"line":260},[183,923,924],{"class":192},"categories ",[183,926,215],{"class":188},[183,928,929],{"class":192}," QgsMapLayer.StyleCategory.Symbology ",[183,931,932],{"class":188},"|",[183,934,935],{"class":192}," QgsMapLayer.StyleCategory.Labeling\n",[183,937,938,940,942,944,947,949],{"class":121,"line":279},[183,939,310],{"class":228},[183,941,313],{"class":192},[183,943,389],{"class":228},[183,945,946],{"class":192},"(categories ",[183,948,355],{"class":188},[183,950,951],{"class":192}," QgsMapLayer.StyleCategory.Labeling))\n",[14,953,954,956,957,960,961,964,965,967,968,970,971,974],{},[346,955,348],{}," Many enums moved to the ",[18,958,959],{},"Qgis"," class during the 3.2x–3.3x series, and QGIS 4 requires the scoped form ",[18,962,963],{},"Class.EnumName.Value",". The documentation of each enum notes when it moved and lists the old name; the old unscoped names still work on 3.x LTRs, so code using the new names runs on both. Flags are enums designed to combine with ",[18,966,932],{}," and test with ",[18,969,355],{},". When an enum value is an integer in older code — ",[18,972,973],{},"TYPE: 0"," in Processing parameters, for example — the docs list the values in order.",[152,976,978],{"id":977},"signals-and-slots","Signals and slots",[14,980,981],{},"Signals appear in their own section of a class's documentation. In Python, a signal is an attribute you connect a function to; its C++ parameters become the arguments your function receives.",[174,983,985],{"className":176,"code":984,"language":178,"meta":179,"style":179},"# C++ signal: void featureAdded(QgsFeatureId fid)\ndef on_added(fid):\n    print(\"feature added:\", fid)\n\nlayer.featureAdded.connect(on_added)\n\n# C++ signal: void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)\nlayer.attributeValueChanged.connect(lambda fid, idx, value: print(fid, idx, value))\n",[18,986,987,992,1004,1017,1021,1026,1030,1035],{"__ignoreMap":179},[183,988,989],{"class":121,"line":185},[183,990,991],{"class":242},"# C++ signal: void featureAdded(QgsFeatureId fid)\n",[183,993,994,997,1001],{"class":121,"line":202},[183,995,996],{"class":188},"def",[183,998,1000],{"class":999},"svObZ"," on_added",[183,1002,1003],{"class":192},"(fid):\n",[183,1005,1006,1009,1011,1014],{"class":121,"line":209},[183,1007,1008],{"class":228},"    print",[183,1010,313],{"class":192},[183,1012,1013],{"class":221},"\"feature added:\"",[183,1015,1016],{"class":192},", fid)\n",[183,1018,1019],{"class":121,"line":234},[183,1020,206],{"emptyLinePlaceholder":205},[183,1022,1023],{"class":121,"line":239},[183,1024,1025],{"class":192},"layer.featureAdded.connect(on_added)\n",[183,1027,1028],{"class":121,"line":246},[183,1029,206],{"emptyLinePlaceholder":205},[183,1031,1032],{"class":121,"line":260},[183,1033,1034],{"class":242},"# C++ signal: void attributeValueChanged(QgsFeatureId fid, int idx, const QVariant &value)\n",[183,1036,1037,1040,1043,1046,1048],{"class":121,"line":279},[183,1038,1039],{"class":192},"layer.attributeValueChanged.connect(",[183,1041,1042],{"class":188},"lambda",[183,1044,1045],{"class":192}," fid, idx, value: ",[183,1047,310],{"class":228},[183,1049,1050],{"class":192},"(fid, idx, value))\n",[14,1052,1053,1055,1056,554],{},[346,1054,348],{}," The signal's parameter list tells you what your handler receives, in order — here a feature id, then for attribute changes the field index and new value. Overloaded signals with several signatures are selected with square-bracket indexing in PyQt, which the docs show when it applies. Disconnect handlers when you no longer need them, especially in plugins, as explained in ",[33,1057,1059],{"href":1058},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Funderstand-qgis-signals-and-slots-pyqgis\u002F","understanding QGIS signals and slots",[152,1061,1063],{"id":1062},"find-the-python-specific-notes","Find the Python-specific notes",[14,1065,1066],{},"Some methods behave differently in Python, and the documentation says so in notes that are easy to miss: \"Not available in Python bindings\", \"In Python, this method returns…\", \"Since QGIS 3.x\". Checking for them saves long debugging sessions.",[174,1068,1070],{"className":176,"code":1069,"language":178,"meta":179,"style":179},"import qgis.core as core\n\ndef api_info(cls_name, method):\n    cls = getattr(core, cls_name, None)\n    if cls is None:\n        return f\"{cls_name} not in qgis.core\"\n    m = getattr(cls, method, None)\n    if m is None:\n        return f\"{cls_name}.{method} not available in Python (check version or bindings notes)\"\n    return (m.__doc__ or \"\").strip().splitlines()[0]\n\nprint(api_info(\"QgsVectorLayer\", \"getFeatures\"))\nprint(api_info(\"QgsGeometry\", \"asWkb\"))\n",[18,1071,1072,1084,1088,1098,1116,1133,1156,1177,1191,1217,1241,1245,1262],{"__ignoreMap":179},[183,1073,1074,1076,1078,1081],{"class":121,"line":185},[183,1075,196],{"class":188},[183,1077,193],{"class":192},[183,1079,1080],{"class":188},"as",[183,1082,1083],{"class":192}," core\n",[183,1085,1086],{"class":121,"line":202},[183,1087,206],{"emptyLinePlaceholder":205},[183,1089,1090,1092,1095],{"class":121,"line":209},[183,1091,996],{"class":188},[183,1093,1094],{"class":999}," api_info",[183,1096,1097],{"class":192},"(cls_name, method):\n",[183,1099,1100,1103,1106,1109,1112,1114],{"class":121,"line":234},[183,1101,1102],{"class":228},"    cls",[183,1104,1105],{"class":188}," =",[183,1107,1108],{"class":228}," getattr",[183,1110,1111],{"class":192},"(core, cls_name, ",[183,1113,674],{"class":228},[183,1115,304],{"class":192},[183,1117,1118,1121,1124,1127,1130],{"class":121,"line":239},[183,1119,1120],{"class":188},"    if",[183,1122,1123],{"class":228}," cls",[183,1125,1126],{"class":188}," is",[183,1128,1129],{"class":228}," None",[183,1131,1132],{"class":192},":\n",[183,1134,1135,1138,1141,1144,1147,1150,1153],{"class":121,"line":246},[183,1136,1137],{"class":188},"        return",[183,1139,1140],{"class":188}," f",[183,1142,1143],{"class":221},"\"",[183,1145,1146],{"class":228},"{",[183,1148,1149],{"class":192},"cls_name",[183,1151,1152],{"class":228},"}",[183,1154,1155],{"class":221}," not in qgis.core\"\n",[183,1157,1158,1161,1163,1165,1167,1170,1173,1175],{"class":121,"line":260},[183,1159,1160],{"class":192},"    m ",[183,1162,215],{"class":188},[183,1164,1108],{"class":228},[183,1166,313],{"class":192},[183,1168,1169],{"class":228},"cls",[183,1171,1172],{"class":192},", method, ",[183,1174,674],{"class":228},[183,1176,304],{"class":192},[183,1178,1179,1181,1184,1187,1189],{"class":121,"line":279},[183,1180,1120],{"class":188},[183,1182,1183],{"class":192}," m ",[183,1185,1186],{"class":188},"is",[183,1188,1129],{"class":228},[183,1190,1132],{"class":192},[183,1192,1193,1195,1197,1199,1201,1203,1205,1207,1209,1212,1214],{"class":121,"line":284},[183,1194,1137],{"class":188},[183,1196,1140],{"class":188},[183,1198,1143],{"class":221},[183,1200,1146],{"class":228},[183,1202,1149],{"class":192},[183,1204,1152],{"class":228},[183,1206,554],{"class":221},[183,1208,1146],{"class":228},[183,1210,1211],{"class":192},"method",[183,1213,1152],{"class":228},[183,1215,1216],{"class":221}," not available in Python (check version or bindings notes)\"\n",[183,1218,1219,1222,1225,1228,1231,1234,1237,1239],{"class":121,"line":290},[183,1220,1221],{"class":188},"    return",[183,1223,1224],{"class":192}," (m.",[183,1226,1227],{"class":228},"__doc__",[183,1229,1230],{"class":188}," or",[183,1232,1233],{"class":221}," \"\"",[183,1235,1236],{"class":192},").strip().splitlines()[",[183,1238,58],{"class":228},[183,1240,231],{"class":192},[183,1242,1243],{"class":121,"line":307},[183,1244,206],{"emptyLinePlaceholder":205},[183,1246,1247,1249,1252,1255,1257,1260],{"class":121,"line":328},[183,1248,310],{"class":228},[183,1250,1251],{"class":192},"(api_info(",[183,1253,1254],{"class":221},"\"QgsVectorLayer\"",[183,1256,21],{"class":192},[183,1258,1259],{"class":221},"\"getFeatures\"",[183,1261,747],{"class":192},[183,1263,1264,1266,1268,1271,1273,1276],{"class":121,"line":333},[183,1265,310],{"class":228},[183,1267,1251],{"class":192},[183,1269,1270],{"class":221},"\"QgsGeometry\"",[183,1272,21],{"class":192},[183,1274,1275],{"class":221},"\"asWkb\"",[183,1277,747],{"class":192},[14,1279,1280,1282,1283,1287,1288,356,1291,1293,1294,554],{},[346,1281,348],{}," Checking that a class and method exist in the running bindings catches the two common cases: a method added in a newer QGIS than the one installed, and a C++ method deliberately not exposed to Python. The first line of the docstring is the Python signature, often more useful than the C++ one. Notes marked \"since QGIS 3.x\" tell you the minimum version — important for plugins that declare a minimum QGIS version, as in ",[33,1284,1286],{"href":1285},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fqgis-python-version-compatibility-guide\u002F","the Python version compatibility guide",". Exploring with ",[18,1289,1290],{},"dir()",[18,1292,403],{}," is covered in ",[33,1295,1297],{"href":1296},"\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fexplore-pyqgis-api-with-dir-and-help\u002F","exploring the PyQGIS API with dir and help",[152,1299,1301],{"id":1300},"qgis-version-compatibility","QGIS version compatibility",[14,1303,1304,1305,790,1307,1309],{},"The documentation is versioned: qgis.org\u002Fpyqgis\u002F3.34\u002F and later each describe their release. Read the version you target, and use the master documentation only for upcoming features. The mapping rules here — const and references vanish, out-parameters become tuples, ",[18,1306,789],{},[18,1308,554],{}," — are stable across QGIS 3 and QGIS 4; QGIS 4 additionally requires scoped enum names.",[152,1311,1313],{"id":1312},"troubleshooting","Troubleshooting",[157,1315,1316,1326,1332,1341],{},[160,1317,1318,1323,1324,554],{},[346,1319,1320,554],{},[18,1321,1322],{},"TypeError: arguments did not match any overloaded call"," An argument has the wrong type; compare with the Python signature in ",[18,1325,403],{},[160,1327,1328,1331],{},[346,1329,1330],{},"A method returns a tuple you did not expect."," It has out-parameters; unpack them.",[160,1333,1334,1340],{},[346,1335,1336,1339],{},[18,1337,1338],{},"AttributeError"," for a documented method."," The method is newer than your QGIS, or not exposed to Python; check the version note.",[160,1342,1343,1346],{},[346,1344,1345],{},"Crashes after passing objects around."," Ownership was transferred; clone before reusing.",[152,1348,1350],{"id":1349},"conclusion","Conclusion",[14,1352,1353,1354,21,1356,356,1358,1360,1361,1363],{},"Read signatures by dropping ",[18,1355,352],{},[18,1357,355],{},[18,1359,359],{},", treat defaults as optional arguments, watch ownership notes and clone transferred objects before reuse, unpack out-parameters from returned tuples, write enums with ",[18,1362,554],{}," and scoped names, connect signals with handlers matching their parameters, and check Python notes and version markers before relying on a method.",[152,1365,1367],{"id":1366},"frequently-asked-questions","Frequently Asked Questions",[14,1369,1370,1373],{},[346,1371,1372],{},"Should I read the C++ or the Python docs?","\nStart with the PyQGIS docs for Python signatures; consult the C++ docs for fuller descriptions and class diagrams.",[14,1375,1376,1383],{},[346,1377,1378,1379,1382],{},"What does ",[18,1380,1381],{},"SIP_SKIP"," mean in sources?","\nThe method is not available in Python.",[14,1385,1386,1389,1390,21,1393,1396],{},[346,1387,1388],{},"Are Qt classes documented on the QGIS site?","\nNo — use the Qt documentation (PyQt or Qt for Python) for ",[18,1391,1392],{},"QColor",[18,1394,1395],{},"QDate"," and other Qt classes.",[14,1398,1399,1402,1403,1405],{},[346,1400,1401],{},"How do I find which class has a method I need?","\nSearch the docs, or ",[18,1404,1290],{}," likely classes in the console; the class hierarchy pages show inherited methods.",[152,1407,1409],{"id":1408},"related","Related",[157,1411,1412,1417,1422,1427,1432],{},[160,1413,1414,1416],{},[33,1415,36],{"href":35}," — the guide this recipe belongs to",[160,1418,1419],{},[33,1420,1421],{"href":1296},"Explore the PyQGIS API with dir and help",[160,1423,1424],{},[33,1425,1426],{"href":552},"QGIS Object Ownership and Crashes in PyQGIS",[160,1428,1429],{},[33,1430,1431],{"href":1285},"QGIS Python Version Compatibility Guide",[160,1433,1434],{},[33,1435,1436],{"href":1058},"Understand QGIS Signals and Slots in PyQGIS",[1438,1439,1440],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .sjoCn, html code.shiki .sjoCn{--shiki-default:#9AA79F}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}",{"title":179,"searchDepth":202,"depth":202,"links":1442},[1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453,1454],{"id":154,"depth":202,"text":155},{"id":168,"depth":202,"text":169},{"id":407,"depth":202,"text":408},{"id":557,"depth":202,"text":558},{"id":773,"depth":202,"text":774},{"id":977,"depth":202,"text":978},{"id":1062,"depth":202,"text":1063},{"id":1300,"depth":202,"text":1301},{"id":1312,"depth":202,"text":1313},{"id":1349,"depth":202,"text":1350},{"id":1366,"depth":202,"text":1367},{"id":1408,"depth":202,"text":1409},"Translate the QGIS API documentation into working Python — reading C++ signatures, pointers, references and const, default arguments, out-parameters that become tuples, enums and flags, signals and slots, and finding the Python-specific notes that change how a method behaves.","md",{"slug":1458,"type":1459,"breadcrumb":1460,"datePublished":1461,"dateModified":1461},"read-pyqgis-api-docs-cpp-signatures","article","Read the API Docs and C++ Signatures","2026-10-02","\u002Fpyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fread-pyqgis-api-docs-cpp-signatures",{"title":5,"description":1455},"pyqgis-fundamentals-environment-setup\u002Fqgis-api-architecture\u002Fread-pyqgis-api-docs-cpp-signatures\u002Findex","HdE6zmti8BCa5tbnK7qTE1OP22iwgDU3cZQSVtIiKAg",1790966252952]