{"kind": "language", "major": "18", "item": {"slug": "c", "name": "c", "name_zh": "", "category": "\u539f\u751f\u51fd\u6570\u8bed\u8a00", "summary": "\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570", "aliases": [], "content_hash": "f0f111c1b1d706bab8752940dc8df953cdcfd004b363e9b0c069746b63d42a55", "versions": {"10": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "PGUID", "laninline": "0", "lanpltrusted": "f", "lanvalidator": "2247", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "label": "10.23", "major": "10", "channel": "historical", "revision": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9", "source_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9", "catalog_fingerprint": "691be281b476dde4374d7f805b2bacc2e75bdef40f1e9d3d42e91f97fe95cfd0"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://pg.center/docs/10/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 10 English manual", "sha256": "038a55caa67446d85698e7834d7f6bc9499f45b994f586e77faa8d5f607cb813", "language": "en", "original_url": "/docs/10/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">37.9.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#XFUNC-C-DYNLOAD\">37.9.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.12.5.4.2.2.1.3\" name=\"id-1.8.3.12.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/10/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.12.5.4.2.3.1.2\" name=\"id-1.8.3.12.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u901a\u8fc7\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/10/xfunc-c.html#DFUNC\" title=\"37.9.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a037.9.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u52a0\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u88c5\u5165\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\uff0cPostgreSQL \u4f1a\u68c0\u67e5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684\u201c\u9b54\u672f\u5757\u201d\u3002\u8fd9\u6837\uff0c\u670d\u52a1\u5668\u80fd\u591f\u53d1\u73b0\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u4e3a\u53e6\u4e00\u4e2a PostgreSQL \u5927\u7248\u672c\u7f16\u8bd1\u7684\u3002\u4ece PostgreSQL 8.2 \u5f00\u59cb\uff0c\u9b54\u672f\u5757\u662f\u5fc5\u9700\u7684\u3002\u8981\u52a0\u5165\u9b54\u672f\u5757\uff0c\u5e94\u5728\u6a21\u5757\u7684\u4e00\u4e2a\u4e14\u4ec5\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff0c\u5305\u542b fmgr.h \u5934\u6587\u4ef6\u540e\u5199\u5165\u4ee5\u4e0b\u5185\u5bb9\uff1a</p>\n<pre class=\"programlisting\">#ifdef PG_MODULE_MAGIC\nPG_MODULE_MAGIC;\n#endif\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u7701\u7565 <code class=\"literal\">#ifdef</code> \u68c0\u67e5\uff0c\u5982\u679c\u4ee3\u7801\u4e0d\u9700\u8981\u9488\u5bf9 8.2 \u4e4b\u524d\u7684 <span class=\"productname\">PostgreSQL</span> \u7248\u672c\u7f16\u8bd1\u7684\u8bdd\u3002</p>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u9009\u62e9\u5305\u542b\u521d\u59cb\u5316\u548c\u7ec8\u7ed3\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u88c5\u8f7d\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_fini</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u5378\u8f7d\u524d\u7acb\u5373\u88ab\u8c03\u7528\u3002\u540c\u6837\uff0c\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u6ce8\u610f\uff0c<code class=\"function\">_PG_fini</code> \u53ea\u4f1a\u5728\u5378\u8f7d\u6587\u4ef6\u65f6\u88ab\u8c03\u7528\uff0c\u800c\u4e0d\u4f1a\u5728\u8fdb\u7a0b\u7ec8\u6b62\u65f6\u88ab\u8c03\u7528\u3002\uff08\u76ee\u524d\uff0c\u5378\u8f7d\u5df2\u88ab\u7981\u7528\uff0c\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\uff0c\u4f46\u5c06\u6765\u53ef\u80fd\u4f1a\u6539\u53d8\u3002\uff09</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#XFUNC-C-BASETYPE\">37.9.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u4e0e\u51fd\u6570\u4f20\u9012\u5b83\u4eec\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/10/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a037.1.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a037.1</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/10/xaggr.html\" title=\"37.10.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a037.10\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/10/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a037.1.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a037.1</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a037.1.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">abstime</code></td>\n<td><code class=\"type\">AbsoluteTime</code></td>\n<td><code class=\"filename\">utils/nabstime.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">reltime</code></td>\n<td><code class=\"type\">RelativeTime</code></td>\n<td><code class=\"filename\">utils/nabstime.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">text</code></td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tinterval</code></td>\n<td><code class=\"type\">TimeInterval</code></td>\n<td><code class=\"filename\">utils/nabstime.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div>\n<br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.12.7\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#id-1.8.3.12.7\">37.9.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n\n#ifdef PG_MODULE_MAGIC\nPG_MODULE_MAGIC;\n#endif\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy((void *) VARDATA(new_t), /* destination */\n           (void *) VARDATA_ANY(t), /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/10/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"37.9.8.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a037.9.8\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/10/triggers.html\" title=\"\u7b2c\u00a038\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a038\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/10/plhandler.html\" title=\"\u7b2c\u00a055\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a055\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.12.8\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#id-1.8.3.12.8\">37.9.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.12.8.3.1.1.1.2\" name=\"id-1.8.3.12.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/10/xfunc-c.html#DFUNC\" title=\"37.9.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a037.9.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/10/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"37.9.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a037.9.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.12.8.3.1.4.1.3\" name=\"id-1.8.3.12.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.12.8.3.1.4.1.5\" name=\"id-1.8.3.12.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#DFUNC\">37.9.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.12.9.2.3\" name=\"id-1.8.3.12.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 3.0 \u7248\u8d77\u9002\u7528\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">HP-UX</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7cfb\u7edf\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">+z</code>\u3002\u4f7f\u7528 <span class=\"application\">GCC</span> \u65f6\u5219\u662f <code class=\"option\">-fPIC</code>\u3002\u7528\u4e8e\u5171\u4eab\u5e93\u7684\u94fe\u63a5\u5668\u9009\u9879\u662f <code class=\"option\">-b</code>\u3002\u56e0\u6b64\uff1a</p>\n<pre class=\"programlisting\">cc +z -c foo.c\n</pre>\n<p lang=\"zh\">\u6216\u8005\uff1a</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff1a</p>\n<pre class=\"programlisting\">ld -b -o foo.sl foo.o\n</pre>\n<p lang=\"zh\"><span class=\"systemitem\">HP-UX</span> \u4f7f\u7528 <code class=\"filename\">.sl</code> \u4f5c\u4e3a\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff0c\u8fd9\u4e0e\u5927\u591a\u6570\u5176\u4ed6\u7cfb\u7edf\u4e0d\u540c\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre></dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre></dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre></dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre></dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre></dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/10/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"37.9.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a037.9.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.12.10\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#id-1.8.3.12.10\">37.9.6. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u7f16\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u5982\u4e0b\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\n#ifdef PG_MODULE_MAGIC\nPG_MODULE_MAGIC;\n#endif\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u5b8f\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.12.11\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#id-1.8.3.12.11\">37.9.7. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#XFUNC-C-RETURN-SET\">37.9.8. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to result slot\n     *\n     * This is obsolete and only present for backward compatibility, viz,\n     * user-defined SRFs that use the deprecated TupleDescGetSlot().\n     */\n    TupleTableSlot *slot;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_UINT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.12.13\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#id-1.8.3.12.13\">37.9.9. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de\u591a\u6001\u7c7b\u578b <code class=\"type\">anyelement</code>\u3001<code class=\"type\">anyarray</code>\u3001<code class=\"type\">anynonarray</code>\u3001<code class=\"type\">anyenum</code> \u548c <code class=\"type\">anyrange</code>\u3002\u5173\u4e8e\u591a\u6001\u51fd\u6570\u7684\u66f4\u8be6\u7ec6\u89e3\u91ca\uff0c\u89c1<a class=\"xref\" href=\"/docs/10/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"37.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a037.2.5\u00a0\u8282</a>\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-TRANSFORM-FUNCTIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#XFUNC-TRANSFORM-FUNCTIONS\">37.9.10. \u8f6c\u6362\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u67d0\u4e9b\u51fd\u6570\u8c03\u7528\u53ef\u4ee5\u5728\u89c4\u5212\u671f\u95f4\u6839\u636e\u51fd\u6570\u7279\u6709\u7684\u5c5e\u6027\u8fdb\u884c\u7b80\u5316\u3002\u4f8b\u5982\uff0c<code class=\"literal\">int4mul(n, 1)</code> \u53ef\u4ee5\u76f4\u63a5\u7b80\u5316\u4e3a <code class=\"literal\">n</code>\u3002\u8981\u5b9a\u4e49\u8fd9\u7c7b\u9488\u5bf9\u7279\u5b9a\u51fd\u6570\u7684\u4f18\u5316\uff0c\u8bf7\u7f16\u5199\u4e00\u4e2a<em class=\"firstterm\">\u8f6c\u6362\u51fd\u6570</em>\uff0c\u5e76\u5c06\u5176 OID \u653e\u5165\u4e3b\u51fd\u6570\u7684 <code class=\"structfield\">protransform</code> \u5b57\u6bb5\u4e2d\uff0c\u8be5\u5b57\u6bb5\u4f4d\u4e8e\u5176 <code class=\"structname\">pg_proc</code> \u9879\u4e2d\u3002\u8f6c\u6362\u51fd\u6570\u5fc5\u987b\u5177\u6709 SQL \u7b7e\u540d <code class=\"literal\">protransform(internal) RETURNS internal</code>\u3002\u53c2\u6570\u5b9e\u9645\u4e0a\u662f <code class=\"type\">FuncExpr *</code>\uff0c\u5b83\u662f\u4e00\u4e2a\u8868\u793a\u4e3b\u51fd\u6570\u8c03\u7528\u7684\u5360\u4f4d\u8282\u70b9\u3002\u5982\u679c\u8f6c\u6362\u51fd\u6570\u5bf9\u8868\u8fbe\u5f0f\u6811\u7684\u5206\u6790\u8bc1\u660e\uff0c\u53ef\u4ee5\u7528\u7b80\u5316\u7684\u8868\u8fbe\u5f0f\u6811\u66ff\u4ee3\u5b83\u6240\u8868\u793a\u7684\u6240\u6709\u53ef\u80fd\u7684\u5177\u4f53\u8c03\u7528\uff0c\u5c31\u6784\u5efa\u5e76\u8fd4\u56de\u8be5\u7b80\u5316\u8868\u8fbe\u5f0f\u3002\u5426\u5219\uff0c\u8fd4\u56de\u4e00\u4e2a <code class=\"literal\">NULL</code> \u6307\u9488\uff08<span class=\"emphasis\"><em>\u4e0d\u662f</em></span> SQL \u7a7a\u503c\uff09\u3002</p>\n<p lang=\"zh\">\u6211\u4eec\u4e0d\u4fdd\u8bc1 <span class=\"productname\">PostgreSQL</span> \u5728\u8f6c\u6362\u51fd\u6570\u53ef\u4ee5\u7b80\u5316\u7684\u60c5\u51b5\u4e0b\u7edd\u4e0d\u4f1a\u8c03\u7528\u4e3b\u51fd\u6570\u3002\u8bf7\u786e\u4fdd\u7b80\u5316\u540e\u7684\u8868\u8fbe\u5f0f\u4e0e\u5b9e\u9645\u8c03\u7528\u4e3b\u51fd\u6570\u4e25\u683c\u7b49\u4ef7\u3002</p>\n<p lang=\"zh\">\u76ee\u524d\uff0c\u51fa\u4e8e\u5b89\u5168\u8003\u8651\uff0c\u8fd9\u9879\u529f\u80fd\u6ca1\u6709\u5728 SQL \u5c42\u9762\u5f00\u653e\u7ed9\u7528\u6237\uff0c\u56e0\u6b64\u5b9e\u9645\u53ea\u80fd\u7528\u4e8e\u4f18\u5316\u5185\u7f6e\u51fd\u6570\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.12.15\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#id-1.8.3.12.15\">37.9.11. \u5171\u4eab\u5185\u5b58\u4e0e LWLocks</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLock \u548c\u4e00\u5757\u5171\u4eab\u5185\u5b58\u3002\u9644\u52a0\u6a21\u5757\u7684\u5171\u4eab\u5e93\u5fc5\u987b\u901a\u8fc7\u5728\u4ee5\u4e0b\u53c2\u6570\u4e2d\u6307\u5b9a\u5b83\u6765\u9884\u88c5\u8f7d\uff1a<a class=\"xref\" href=\"/docs/10/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a><a class=\"indexterm\" id=\"id-1.8.3.12.15.2.2\" name=\"id-1.8.3.12.15.2.2\"></a>\u3002\u5171\u4eab\u5185\u5b58\u53ef\u4ee5\u901a\u8fc7\u4e0b\u9762\u7684\u8c03\u7528\u6765\u9884\u7559\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(int size)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728\u4f60\u7684 <code class=\"function\">_PG_init</code> \u51fd\u6570\u4e2d\u3002</p>\n<p lang=\"zh\">\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728 <code class=\"function\">_PG_init</code> \u4e2d\u3002\u8fd9\u6837\u53ef\u4ee5\u786e\u4fdd\u4e00\u4e2a\u5305\u542b <code class=\"literal\">num_lwlocks</code> \u4e2a LWLock \u7684\u6570\u7ec4\u53ef\u901a\u8fc7\u4ee5\u4e0b\u540d\u79f0\u8bbf\u95ee\uff1a<code class=\"literal\">tranche_name</code>\u3002\u4f7f\u7528 <code class=\"function\">GetNamedLWLockTranche</code> \u53ef\u4ee5\u53d6\u5f97\u6307\u5411\u8be5\u6570\u7ec4\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u6001\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u9644\u52a0\u5230\u5176\u5206\u914d\u7684\u5171\u4eab\u5185\u5b58\u5e76\u8fdb\u884c\u521d\u59cb\u5316\u65f6\uff0c\u90fd\u5e94\u4f7f\u7528\u8f7b\u91cf\u7ea7\u9501 AddinShmemInitLock\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\n\nif (!ptr)\n{\n        bool    found;\n\n        LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\n        ptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\n        if (!found)\n        {\n                initialize contents of shmem area;\n                acquire any requested LWLocks using:\n                ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n        }\n        LWLockRelease(AddinShmemInitLock);\n}\n</pre></div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/10/xfunc-c.html#EXTEND-CPP\">37.9.12. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/10/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/10/xfunc-c.html", "method": "same-major semantic node", "sha256": "0df98937379292051379860f0a86609d1855b9c9df04dfb53c02ec0380079453", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/p[10]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[10]/p[2]", "#XFUNC-C/div[10]/p[6]", "#XFUNC-C/div[10]/p[7]", "#XFUNC-C/div[10]/p[8]", "#XFUNC-C/div[11]/div[7]/p[1]", "#XFUNC-C/div[11]/div[8]/p[1]", "#XFUNC-C/div[11]/p[11]", "#XFUNC-C/div[11]/p[13]", "#XFUNC-C/div[11]/p[14]", "#XFUNC-C/div[11]/p[16]", "#XFUNC-C/div[11]/p[18]", "#XFUNC-C/div[11]/p[19]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[21]", "#XFUNC-C/div[11]/p[22]", "#XFUNC-C/div[11]/p[24]", "#XFUNC-C/div[11]/p[25]", "#XFUNC-C/div[11]/p[27]", "#XFUNC-C/div[11]/p[28]", "#XFUNC-C/div[11]/p[3]", "#XFUNC-C/div[11]/p[4]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[9]", "#XFUNC-C/div[12]/div[19]/p[1]", "#XFUNC-C/div[12]/p[10]", "#XFUNC-C/div[12]/p[12]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[15]", "#XFUNC-C/div[12]/p[20]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[26]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[2]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[8]", "#XFUNC-C/div[13]/p[1]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[14]/p[1]", "#XFUNC-C/div[14]/p[2]", "#XFUNC-C/div[14]/p[3]", "#XFUNC-C/div[15]/p[1]", "#XFUNC-C/div[15]/p[3]", "#XFUNC-C/div[15]/p[6]", "#XFUNC-C/div[16]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[16]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[16]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[16]/p[2]", "#XFUNC-C/div[16]/p[4]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[11]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[13]", "#XFUNC-C/div[5]/p[14]", "#XFUNC-C/div[5]/p[19]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[1]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[4]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[12]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[14]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[4]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[6]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/10/description/0": "dynamically-loaded C functions", "/versions/10/facts/0/label": "Kind", "/versions/10/facts/0/value": "Native function language", "/versions/10/facts/1/label": "Trusted", "/versions/10/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "6dcdb7120d588afff61e7662868e9cd925a1b2b3ec91d8b5a69bd0775c53ede3"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "11": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "PGUID", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "label": "11.22", "major": "11", "channel": "historical", "revision": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0", "source_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0", "catalog_fingerprint": "8f21f4444b7f68923f4762af0eb7937fa2907026e91249483e79050de012c901"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://pg.center/docs/11/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 11 English manual", "sha256": "9e1cd39e5b6e7b390fd9b89de261253773c874a029e0a7369932ac5c75211b2c", "language": "en", "original_url": "/docs/11/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">38.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#XFUNC-C-DYNLOAD\">38.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/11/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u901a\u8fc7\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/11/xfunc-c.html#DFUNC\" title=\"38.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a038.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u9009\u62e9\u5305\u542b\u521d\u59cb\u5316\u548c\u7ec8\u7ed3\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u88c5\u8f7d\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_fini</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u5378\u8f7d\u524d\u7acb\u5373\u88ab\u8c03\u7528\u3002\u540c\u6837\uff0c\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u6ce8\u610f\uff0c<code class=\"function\">_PG_fini</code> \u53ea\u4f1a\u5728\u5378\u8f7d\u6587\u4ef6\u65f6\u88ab\u8c03\u7528\uff0c\u800c\u4e0d\u4f1a\u5728\u8fdb\u7a0b\u7ec8\u6b62\u65f6\u88ab\u8c03\u7528\u3002\uff08\u76ee\u524d\uff0c\u5378\u8f7d\u5df2\u88ab\u7981\u7528\uff0c\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\uff0c\u4f46\u5c06\u6765\u53ef\u80fd\u4f1a\u6539\u53d8\u3002\uff09</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#XFUNC-C-BASETYPE\">38.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u4e0e\u51fd\u6570\u4f20\u9012\u5b83\u4eec\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/11/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a038.1.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a038.1</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/11/xaggr.html\" title=\"38.11.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a038.11\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/11/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a038.1.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a038.1</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a038.1.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">abstime</code></td>\n<td><code class=\"type\">AbsoluteTime</code></td>\n<td><code class=\"filename\">utils/nabstime.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">reltime</code></td>\n<td><code class=\"type\">RelativeTime</code></td>\n<td><code class=\"filename\">utils/nabstime.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">text</code></td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tinterval</code></td>\n<td><code class=\"type\">TimeInterval</code></td>\n<td><code class=\"filename\">utils/nabstime.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.7\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#id-1.8.3.13.7\">38.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy((void *) VARDATA(new_t), /* destination */\n           (void *) VARDATA_ANY(t), /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/11/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"38.10.8.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a038.10.8\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/11/triggers.html\" title=\"\u7b2c\u00a039\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a039\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/11/plhandler.html\" title=\"\u7b2c\u00a056\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a056\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.8\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#id-1.8.3.13.8\">38.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/11/xfunc-c.html#DFUNC\" title=\"38.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a038.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/11/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"38.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a038.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#DFUNC\">38.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 3.0 \u7248\u8d77\u9002\u7528\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">HP-UX</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7cfb\u7edf\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">+z</code>\u3002\u4f7f\u7528 <span class=\"application\">GCC</span> \u65f6\u5219\u662f <code class=\"option\">-fPIC</code>\u3002\u7528\u4e8e\u5171\u4eab\u5e93\u7684\u94fe\u63a5\u5668\u9009\u9879\u662f <code class=\"option\">-b</code>\u3002\u56e0\u6b64\uff1a</p>\n<pre class=\"programlisting\">cc +z -c foo.c\n</pre>\n<p lang=\"zh\">\u6216\u8005\uff1a</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff1a</p>\n<pre class=\"programlisting\">ld -b -o foo.sl foo.o\n</pre>\n<p lang=\"zh\"><span class=\"systemitem\">HP-UX</span> \u4f7f\u7528 <code class=\"filename\">.sl</code> \u4f5c\u4e3a\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff0c\u8fd9\u4e0e\u5927\u591a\u6570\u5176\u4ed6\u7cfb\u7edf\u4e0d\u540c\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/11/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"38.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a038.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.10\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#id-1.8.3.13.10\">38.10.6. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u5b8f\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.11\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#id-1.8.3.13.11\">38.10.7. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#XFUNC-C-RETURN-SET\">38.10.8. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to result slot\n     *\n     * This is obsolete and only present for backward compatibility, viz,\n     * user-defined SRFs that use the deprecated TupleDescGetSlot().\n     */\n    TupleTableSlot *slot;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_UINT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.13\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#id-1.8.3.13.13\">38.10.9. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de\u591a\u6001\u7c7b\u578b <code class=\"type\">anyelement</code>\u3001<code class=\"type\">anyarray</code>\u3001<code class=\"type\">anynonarray</code>\u3001<code class=\"type\">anyenum</code> \u548c <code class=\"type\">anyrange</code>\u3002\u5173\u4e8e\u591a\u6001\u51fd\u6570\u7684\u66f4\u8be6\u7ec6\u89e3\u91ca\uff0c\u89c1<a class=\"xref\" href=\"/docs/11/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"38.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a038.2.5\u00a0\u8282</a>\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-TRANSFORM-FUNCTIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#XFUNC-TRANSFORM-FUNCTIONS\">38.10.10. \u8f6c\u6362\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u67d0\u4e9b\u51fd\u6570\u8c03\u7528\u53ef\u4ee5\u5728\u89c4\u5212\u671f\u95f4\u6839\u636e\u51fd\u6570\u7279\u6709\u7684\u5c5e\u6027\u8fdb\u884c\u7b80\u5316\u3002\u4f8b\u5982\uff0c<code class=\"literal\">int4mul(n, 1)</code> \u53ef\u4ee5\u76f4\u63a5\u7b80\u5316\u4e3a <code class=\"literal\">n</code>\u3002\u8981\u5b9a\u4e49\u8fd9\u7c7b\u9488\u5bf9\u7279\u5b9a\u51fd\u6570\u7684\u4f18\u5316\uff0c\u8bf7\u7f16\u5199\u4e00\u4e2a<em class=\"firstterm\">\u8f6c\u6362\u51fd\u6570</em>\uff0c\u5e76\u5c06\u5176 OID \u653e\u5165\u4e3b\u51fd\u6570\u7684 <code class=\"structfield\">protransform</code> \u5b57\u6bb5\u4e2d\uff0c\u8be5\u5b57\u6bb5\u4f4d\u4e8e\u5176 <code class=\"structname\">pg_proc</code> \u9879\u4e2d\u3002\u8f6c\u6362\u51fd\u6570\u5fc5\u987b\u5177\u6709 SQL \u7b7e\u540d <code class=\"literal\">protransform(internal) RETURNS internal</code>\u3002\u53c2\u6570\u5b9e\u9645\u4e0a\u662f <code class=\"type\">FuncExpr *</code>\uff0c\u5b83\u662f\u4e00\u4e2a\u8868\u793a\u4e3b\u51fd\u6570\u8c03\u7528\u7684\u5360\u4f4d\u8282\u70b9\u3002\u5982\u679c\u8f6c\u6362\u51fd\u6570\u5bf9\u8868\u8fbe\u5f0f\u6811\u7684\u5206\u6790\u8bc1\u660e\uff0c\u53ef\u4ee5\u7528\u7b80\u5316\u7684\u8868\u8fbe\u5f0f\u6811\u66ff\u4ee3\u5b83\u6240\u8868\u793a\u7684\u6240\u6709\u53ef\u80fd\u7684\u5177\u4f53\u8c03\u7528\uff0c\u5c31\u6784\u5efa\u5e76\u8fd4\u56de\u8be5\u7b80\u5316\u8868\u8fbe\u5f0f\u3002\u5426\u5219\uff0c\u8fd4\u56de\u4e00\u4e2a <code class=\"literal\">NULL</code> \u6307\u9488\uff08<span class=\"emphasis\"><em>\u4e0d\u662f</em></span> SQL \u7a7a\u503c\uff09\u3002</p>\n<p lang=\"zh\">\u6211\u4eec\u4e0d\u4fdd\u8bc1 <span class=\"productname\">PostgreSQL</span> \u5728\u8f6c\u6362\u51fd\u6570\u53ef\u4ee5\u7b80\u5316\u7684\u60c5\u51b5\u4e0b\u7edd\u4e0d\u4f1a\u8c03\u7528\u4e3b\u51fd\u6570\u3002\u8bf7\u786e\u4fdd\u7b80\u5316\u540e\u7684\u8868\u8fbe\u5f0f\u4e0e\u5b9e\u9645\u8c03\u7528\u4e3b\u51fd\u6570\u4e25\u683c\u7b49\u4ef7\u3002</p>\n<p lang=\"zh\">\u76ee\u524d\uff0c\u51fa\u4e8e\u5b89\u5168\u8003\u8651\uff0c\u8fd9\u9879\u529f\u80fd\u6ca1\u6709\u5728 SQL \u5c42\u9762\u5f00\u653e\u7ed9\u7528\u6237\uff0c\u56e0\u6b64\u5b9e\u9645\u53ea\u80fd\u7528\u4e8e\u4f18\u5316\u5185\u7f6e\u51fd\u6570\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.15\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#id-1.8.3.13.15\">38.10.11. \u5171\u4eab\u5185\u5b58\u4e0e LWLocks</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLock \u548c\u4e00\u5757\u5171\u4eab\u5185\u5b58\u3002\u9644\u52a0\u6a21\u5757\u7684\u5171\u4eab\u5e93\u5fc5\u987b\u901a\u8fc7\u5728\u4ee5\u4e0b\u53c2\u6570\u4e2d\u6307\u5b9a\u5b83\u6765\u9884\u88c5\u8f7d\uff1a<a class=\"xref\" href=\"/docs/11/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a><a class=\"indexterm\" id=\"id-1.8.3.13.15.2.2\" name=\"id-1.8.3.13.15.2.2\"></a>\u3002\u5171\u4eab\u5185\u5b58\u53ef\u4ee5\u901a\u8fc7\u4e0b\u9762\u7684\u8c03\u7528\u6765\u9884\u7559\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(int size)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728\u4f60\u7684 <code class=\"function\">_PG_init</code> \u51fd\u6570\u4e2d\u3002</p>\n<p lang=\"zh\">\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728 <code class=\"function\">_PG_init</code> \u4e2d\u3002\u8fd9\u6837\u53ef\u4ee5\u786e\u4fdd\u4e00\u4e2a\u5305\u542b <code class=\"literal\">num_lwlocks</code> \u4e2a LWLock \u7684\u6570\u7ec4\u53ef\u901a\u8fc7\u4ee5\u4e0b\u540d\u79f0\u8bbf\u95ee\uff1a<code class=\"literal\">tranche_name</code>\u3002\u4f7f\u7528 <code class=\"function\">GetNamedLWLockTranche</code> \u53ef\u4ee5\u53d6\u5f97\u6307\u5411\u8be5\u6570\u7ec4\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u6001\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u9644\u52a0\u5230\u5176\u5206\u914d\u7684\u5171\u4eab\u5185\u5b58\u5e76\u8fdb\u884c\u521d\u59cb\u5316\u65f6\uff0c\u90fd\u5e94\u4f7f\u7528\u8f7b\u91cf\u7ea7\u9501 AddinShmemInitLock\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\n\nif (!ptr)\n{\n        bool    found;\n\n        LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\n        ptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\n        if (!found)\n        {\n                initialize contents of shmem area;\n                acquire any requested LWLocks using:\n                ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n        }\n        LWLockRelease(AddinShmemInitLock);\n}\n</pre>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/11/xfunc-c.html#EXTEND-CPP\">38.10.12. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/11/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/11/xfunc-c.html", "method": "same-major semantic node", "sha256": "338b6447b1144585971c12bdf32b24efc4b9b5a4778aff31b878afd575c1c68c", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/p[10]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[10]/p[2]", "#XFUNC-C/div[10]/p[6]", "#XFUNC-C/div[10]/p[7]", "#XFUNC-C/div[10]/p[8]", "#XFUNC-C/div[11]/div[7]/p[1]", "#XFUNC-C/div[11]/div[8]/p[1]", "#XFUNC-C/div[11]/p[11]", "#XFUNC-C/div[11]/p[13]", "#XFUNC-C/div[11]/p[14]", "#XFUNC-C/div[11]/p[16]", "#XFUNC-C/div[11]/p[18]", "#XFUNC-C/div[11]/p[19]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[21]", "#XFUNC-C/div[11]/p[22]", "#XFUNC-C/div[11]/p[24]", "#XFUNC-C/div[11]/p[25]", "#XFUNC-C/div[11]/p[27]", "#XFUNC-C/div[11]/p[28]", "#XFUNC-C/div[11]/p[3]", "#XFUNC-C/div[11]/p[4]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[9]", "#XFUNC-C/div[12]/div[19]/p[1]", "#XFUNC-C/div[12]/p[10]", "#XFUNC-C/div[12]/p[12]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[15]", "#XFUNC-C/div[12]/p[20]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[26]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[2]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[8]", "#XFUNC-C/div[13]/p[1]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[14]/p[1]", "#XFUNC-C/div[14]/p[2]", "#XFUNC-C/div[14]/p[3]", "#XFUNC-C/div[15]/p[1]", "#XFUNC-C/div[15]/p[3]", "#XFUNC-C/div[15]/p[6]", "#XFUNC-C/div[16]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[16]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[16]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[16]/p[2]", "#XFUNC-C/div[16]/p[4]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[11]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[11]", "#XFUNC-C/div[5]/p[13]", "#XFUNC-C/div[5]/p[18]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[1]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[4]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[12]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[14]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[4]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[6]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/11/description/0": "dynamically-loaded C functions", "/versions/11/facts/0/label": "Kind", "/versions/11/facts/0/value": "Native function language", "/versions/11/facts/1/label": "Trusted", "/versions/11/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "7c069d48416c8b612a4af6777f09cba98a2c80a07e225226e3c84076da017102"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "12": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "PGUID", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "label": "12.22", "major": "12", "channel": "historical", "revision": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b", "source_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b", "catalog_fingerprint": "9f857f4ee4875f9c7de6bfc9df4b757dec8b3a0bb88eadb519c7bd267bd56149"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://pg.center/docs/12/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 12 English manual", "sha256": "b20205ba0b24459d1c84ae8bc91fd01394034f06e30832b53cd2257115e779a1", "language": "en", "original_url": "/docs/12/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">37.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#XFUNC-C-DYNLOAD\">37.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/12/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u901a\u8fc7\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/12/xfunc-c.html#DFUNC\" title=\"37.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a037.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u9009\u62e9\u5305\u542b\u521d\u59cb\u5316\u548c\u7ec8\u7ed3\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u88c5\u8f7d\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_fini</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u5378\u8f7d\u524d\u7acb\u5373\u88ab\u8c03\u7528\u3002\u540c\u6837\uff0c\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u6ce8\u610f\uff0c<code class=\"function\">_PG_fini</code> \u53ea\u4f1a\u5728\u5378\u8f7d\u6587\u4ef6\u65f6\u88ab\u8c03\u7528\uff0c\u800c\u4e0d\u4f1a\u5728\u8fdb\u7a0b\u7ec8\u6b62\u65f6\u88ab\u8c03\u7528\u3002\uff08\u76ee\u524d\uff0c\u5378\u8f7d\u5df2\u88ab\u7981\u7528\uff0c\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\uff0c\u4f46\u5c06\u6765\u53ef\u80fd\u4f1a\u6539\u53d8\u3002\uff09</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#XFUNC-C-BASETYPE\">37.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u4e0e\u51fd\u6570\u4f20\u9012\u5b83\u4eec\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/12/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a037.1.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a037.1</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/12/xaggr.html\" title=\"37.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a037.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/12/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a037.1.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a037.1</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a037.1.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">text</code></td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.7\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#id-1.8.3.13.7\">37.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy((void *) VARDATA(new_t), /* destination */\n           (void *) VARDATA_ANY(t), /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/12/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"37.10.8.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a037.10.8\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/12/triggers.html\" title=\"\u7b2c\u00a038\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a038\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/12/plhandler.html\" title=\"\u7b2c\u00a055\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a055\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.8\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#id-1.8.3.13.8\">37.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/12/xfunc-c.html#DFUNC\" title=\"37.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a037.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/12/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"37.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a037.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#DFUNC\">37.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 3.0 \u7248\u8d77\u9002\u7528\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">HP-UX</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7cfb\u7edf\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">+z</code>\u3002\u4f7f\u7528 <span class=\"application\">GCC</span> \u65f6\u5219\u662f <code class=\"option\">-fPIC</code>\u3002\u7528\u4e8e\u5171\u4eab\u5e93\u7684\u94fe\u63a5\u5668\u9009\u9879\u662f <code class=\"option\">-b</code>\u3002\u56e0\u6b64\uff1a</p>\n<pre class=\"programlisting\">cc +z -c foo.c\n</pre>\n<p lang=\"zh\">\u6216\u8005\uff1a</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff1a</p>\n<pre class=\"programlisting\">ld -b -o foo.sl foo.o\n</pre>\n<p lang=\"zh\"><span class=\"systemitem\">HP-UX</span> \u4f7f\u7528 <code class=\"filename\">.sl</code> \u4f5c\u4e3a\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff0c\u8fd9\u4e0e\u5927\u591a\u6570\u5176\u4ed6\u7cfb\u7edf\u4e0d\u540c\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/12/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"37.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a037.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.10\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#id-1.8.3.13.10\">37.10.6. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u5b8f\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.11\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#id-1.8.3.13.11\">37.10.7. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#XFUNC-C-RETURN-SET\">37.10.8. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_UINT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.13\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#id-1.8.3.13.13\">37.10.9. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de\u591a\u6001\u7c7b\u578b <code class=\"type\">anyelement</code>\u3001<code class=\"type\">anyarray</code>\u3001<code class=\"type\">anynonarray</code>\u3001<code class=\"type\">anyenum</code> \u548c <code class=\"type\">anyrange</code>\u3002\u5173\u4e8e\u591a\u6001\u51fd\u6570\u7684\u66f4\u8be6\u7ec6\u89e3\u91ca\uff0c\u89c1<a class=\"xref\" href=\"/docs/12/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"37.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a037.2.5\u00a0\u8282</a>\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.14\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#id-1.8.3.13.14\">37.10.10. \u5171\u4eab\u5185\u5b58\u4e0e LWLocks</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLock \u548c\u4e00\u5757\u5171\u4eab\u5185\u5b58\u3002\u9644\u52a0\u6a21\u5757\u7684\u5171\u4eab\u5e93\u5fc5\u987b\u901a\u8fc7\u5728\u4ee5\u4e0b\u53c2\u6570\u4e2d\u6307\u5b9a\u5b83\u6765\u9884\u88c5\u8f7d\uff1a<a class=\"xref\" href=\"/docs/12/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a><a class=\"indexterm\" id=\"id-1.8.3.13.14.2.2\" name=\"id-1.8.3.13.14.2.2\"></a>\u3002\u5171\u4eab\u5185\u5b58\u53ef\u4ee5\u901a\u8fc7\u4e0b\u9762\u7684\u8c03\u7528\u6765\u9884\u7559\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(int size)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728\u4f60\u7684 <code class=\"function\">_PG_init</code> \u51fd\u6570\u4e2d\u3002</p>\n<p lang=\"zh\">\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728 <code class=\"function\">_PG_init</code> \u4e2d\u3002\u8fd9\u6837\u53ef\u4ee5\u786e\u4fdd\u4e00\u4e2a\u5305\u542b <code class=\"literal\">num_lwlocks</code> \u4e2a LWLock \u7684\u6570\u7ec4\u53ef\u901a\u8fc7\u4ee5\u4e0b\u540d\u79f0\u8bbf\u95ee\uff1a<code class=\"literal\">tranche_name</code>\u3002\u4f7f\u7528 <code class=\"function\">GetNamedLWLockTranche</code> \u53ef\u4ee5\u53d6\u5f97\u6307\u5411\u8be5\u6570\u7ec4\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u6001\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u9644\u52a0\u5230\u5176\u5206\u914d\u7684\u5171\u4eab\u5185\u5b58\u5e76\u8fdb\u884c\u521d\u59cb\u5316\u65f6\uff0c\u90fd\u5e94\u4f7f\u7528\u8f7b\u91cf\u7ea7\u9501 AddinShmemInitLock\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\n\nif (!ptr)\n{\n        bool    found;\n\n        LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\n        ptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\n        if (!found)\n        {\n                initialize contents of shmem area;\n                acquire any requested LWLocks using:\n                ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n        }\n        LWLockRelease(AddinShmemInitLock);\n}\n</pre>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/12/xfunc-c.html#EXTEND-CPP\">37.10.11. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/12/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/12/xfunc-c.html", "method": "same-major semantic node", "sha256": "b25a73df45087a8fdc374e82b6439c1e121ac685f86ab05f852f86fb2d32f749", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/p[10]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[10]/p[2]", "#XFUNC-C/div[10]/p[6]", "#XFUNC-C/div[10]/p[7]", "#XFUNC-C/div[10]/p[8]", "#XFUNC-C/div[11]/div[7]/p[1]", "#XFUNC-C/div[11]/div[8]/p[1]", "#XFUNC-C/div[11]/p[11]", "#XFUNC-C/div[11]/p[13]", "#XFUNC-C/div[11]/p[14]", "#XFUNC-C/div[11]/p[16]", "#XFUNC-C/div[11]/p[18]", "#XFUNC-C/div[11]/p[19]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[21]", "#XFUNC-C/div[11]/p[22]", "#XFUNC-C/div[11]/p[24]", "#XFUNC-C/div[11]/p[25]", "#XFUNC-C/div[11]/p[27]", "#XFUNC-C/div[11]/p[28]", "#XFUNC-C/div[11]/p[3]", "#XFUNC-C/div[11]/p[4]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[9]", "#XFUNC-C/div[12]/div[19]/p[1]", "#XFUNC-C/div[12]/p[10]", "#XFUNC-C/div[12]/p[12]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[15]", "#XFUNC-C/div[12]/p[20]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[26]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[2]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[8]", "#XFUNC-C/div[13]/p[1]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[14]/p[1]", "#XFUNC-C/div[14]/p[3]", "#XFUNC-C/div[14]/p[6]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[15]/p[2]", "#XFUNC-C/div[15]/p[4]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[11]", "#XFUNC-C/div[5]/p[13]", "#XFUNC-C/div[5]/p[18]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[12]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[14]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[4]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[6]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/12/description/0": "dynamically-loaded C functions", "/versions/12/facts/0/label": "Kind", "/versions/12/facts/0/value": "Native function language", "/versions/12/facts/1/label": "Trusted", "/versions/12/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "bcdf571b5ca958ffcd7525bd8347f0b2018d380b94db2dbd86732d2c2efa596f"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "13": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "PGUID", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "label": "13.23", "major": "13", "channel": "historical", "revision": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6", "source_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6", "catalog_fingerprint": "c7015c845255c9d721c547c8ab9ef37825d332588c9691d982e6906b7d571002"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://pg.center/docs/13/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 13 English manual", "sha256": "868dafae8788b27c58490e1e8dc0b8004cf14f1ab9b5ccd85f8888ddaf582662", "language": "en", "original_url": "/docs/13/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">37.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#XFUNC-C-DYNLOAD\">37.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/13/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u901a\u8fc7\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/13/xfunc-c.html#DFUNC\" title=\"37.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a037.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u9009\u62e9\u5305\u542b\u521d\u59cb\u5316\u548c\u7ec8\u7ed3\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u88c5\u8f7d\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_fini</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u5378\u8f7d\u524d\u7acb\u5373\u88ab\u8c03\u7528\u3002\u540c\u6837\uff0c\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u6ce8\u610f\uff0c<code class=\"function\">_PG_fini</code> \u53ea\u4f1a\u5728\u5378\u8f7d\u6587\u4ef6\u65f6\u88ab\u8c03\u7528\uff0c\u800c\u4e0d\u4f1a\u5728\u8fdb\u7a0b\u7ec8\u6b62\u65f6\u88ab\u8c03\u7528\u3002\uff08\u76ee\u524d\uff0c\u5378\u8f7d\u5df2\u88ab\u7981\u7528\uff0c\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\uff0c\u4f46\u5c06\u6765\u53ef\u80fd\u4f1a\u6539\u53d8\u3002\uff09</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#XFUNC-C-BASETYPE\">37.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u4e0e\u51fd\u6570\u4f20\u9012\u5b83\u4eec\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/13/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a037.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a037.2</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/13/xaggr.html\" title=\"37.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a037.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/13/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a037.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a037.2</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a037.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">text</code></td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.7\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#id-1.8.3.13.7\">37.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy((void *) VARDATA(new_t), /* destination */\n           (void *) VARDATA_ANY(t), /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/13/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"37.10.8.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a037.10.8\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/13/triggers.html\" title=\"\u7b2c\u00a038\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a038\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/13/plhandler.html\" title=\"\u7b2c\u00a055\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a055\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.8\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#id-1.8.3.13.8\">37.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/13/xfunc-c.html#DFUNC\" title=\"37.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a037.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/13/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"37.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a037.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#DFUNC\">37.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 3.0 \u7248\u8d77\u9002\u7528\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">HP-UX</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7cfb\u7edf\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">+z</code>\u3002\u4f7f\u7528 <span class=\"application\">GCC</span> \u65f6\u5219\u662f <code class=\"option\">-fPIC</code>\u3002\u7528\u4e8e\u5171\u4eab\u5e93\u7684\u94fe\u63a5\u5668\u9009\u9879\u662f <code class=\"option\">-b</code>\u3002\u56e0\u6b64\uff1a</p>\n<pre class=\"programlisting\">cc +z -c foo.c\n</pre>\n<p lang=\"zh\">\u6216\u8005\uff1a</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff1a</p>\n<pre class=\"programlisting\">ld -b -o foo.sl foo.o\n</pre>\n<p lang=\"zh\"><span class=\"systemitem\">HP-UX</span> \u4f7f\u7528 <code class=\"filename\">.sl</code> \u4f5c\u4e3a\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff0c\u8fd9\u4e0e\u5927\u591a\u6570\u5176\u4ed6\u7cfb\u7edf\u4e0d\u540c\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/13/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"37.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a037.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.10\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#id-1.8.3.13.10\">37.10.6. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u5b8f\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.11\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#id-1.8.3.13.11\">37.10.7. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#XFUNC-C-RETURN-SET\">37.10.8. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_UINT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.13\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#id-1.8.3.13.13\">37.10.9. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de<a class=\"xref\" href=\"/docs/13/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"37.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a037.2.5\u00a0\u8282</a>\u4e2d\u63cf\u8ff0\u7684\u591a\u6001\u7c7b\u578b\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-SHARED-ADDIN\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#XFUNC-SHARED-ADDIN\">37.10.10. \u5171\u4eab\u5185\u5b58\u4e0e LWLocks</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLock \u548c\u4e00\u5757\u5171\u4eab\u5185\u5b58\u3002\u9644\u52a0\u6a21\u5757\u7684\u5171\u4eab\u5e93\u5fc5\u987b\u901a\u8fc7\u5728\u4ee5\u4e0b\u53c2\u6570\u4e2d\u6307\u5b9a\u5b83\u6765\u9884\u88c5\u8f7d\uff1a<a class=\"xref\" href=\"/docs/13/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a><a class=\"indexterm\" id=\"id-1.8.3.13.14.2.2\" name=\"id-1.8.3.13.14.2.2\"></a>\u3002\u5171\u4eab\u5185\u5b58\u53ef\u4ee5\u901a\u8fc7\u4e0b\u9762\u7684\u8c03\u7528\u6765\u9884\u7559\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(int size)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728\u4f60\u7684 <code class=\"function\">_PG_init</code> \u51fd\u6570\u4e2d\u3002</p>\n<p lang=\"zh\">\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728 <code class=\"function\">_PG_init</code> \u4e2d\u3002\u8fd9\u6837\u53ef\u4ee5\u786e\u4fdd\u4e00\u4e2a\u5305\u542b <code class=\"literal\">num_lwlocks</code> \u4e2a LWLock \u7684\u6570\u7ec4\u53ef\u901a\u8fc7\u4ee5\u4e0b\u540d\u79f0\u8bbf\u95ee\uff1a<code class=\"literal\">tranche_name</code>\u3002\u4f7f\u7528 <code class=\"function\">GetNamedLWLockTranche</code> \u53ef\u4ee5\u53d6\u5f97\u6307\u5411\u8be5\u6570\u7ec4\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u6001\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u9644\u52a0\u5230\u5176\u5206\u914d\u7684\u5171\u4eab\u5185\u5b58\u5e76\u8fdb\u884c\u521d\u59cb\u5316\u65f6\uff0c\u90fd\u5e94\u4f7f\u7528\u8f7b\u91cf\u7ea7\u9501 AddinShmemInitLock\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\n\nif (!ptr)\n{\n        bool    found;\n\n        LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\n        ptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\n        if (!found)\n        {\n                initialize contents of shmem area;\n                acquire any requested LWLocks using:\n                ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n        }\n        LWLockRelease(AddinShmemInitLock);\n}\n</pre>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/13/xfunc-c.html#EXTEND-CPP\">37.10.11. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/13/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/13/xfunc-c.html", "method": "same-major semantic node", "sha256": "095469efa3baa961b27032ae79fbe7a17909a3ff9341e854497b97168d4a1271", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/p[10]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[10]/p[2]", "#XFUNC-C/div[10]/p[6]", "#XFUNC-C/div[10]/p[7]", "#XFUNC-C/div[10]/p[8]", "#XFUNC-C/div[11]/div[7]/p[1]", "#XFUNC-C/div[11]/div[8]/p[1]", "#XFUNC-C/div[11]/p[11]", "#XFUNC-C/div[11]/p[13]", "#XFUNC-C/div[11]/p[14]", "#XFUNC-C/div[11]/p[16]", "#XFUNC-C/div[11]/p[18]", "#XFUNC-C/div[11]/p[19]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[21]", "#XFUNC-C/div[11]/p[22]", "#XFUNC-C/div[11]/p[24]", "#XFUNC-C/div[11]/p[25]", "#XFUNC-C/div[11]/p[27]", "#XFUNC-C/div[11]/p[28]", "#XFUNC-C/div[11]/p[3]", "#XFUNC-C/div[11]/p[4]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[9]", "#XFUNC-C/div[12]/div[19]/p[1]", "#XFUNC-C/div[12]/p[10]", "#XFUNC-C/div[12]/p[12]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[15]", "#XFUNC-C/div[12]/p[20]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[26]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[2]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[8]", "#XFUNC-C/div[13]/p[1]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[14]/p[1]", "#XFUNC-C/div[14]/p[3]", "#XFUNC-C/div[14]/p[6]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[15]/p[2]", "#XFUNC-C/div[15]/p[4]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[11]", "#XFUNC-C/div[5]/p[13]", "#XFUNC-C/div[5]/p[18]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[12]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[14]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[4]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[6]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/13/description/0": "dynamically-loaded C functions", "/versions/13/facts/0/label": "Kind", "/versions/13/facts/0/value": "Native function language", "/versions/13/facts/1/label": "Trusted", "/versions/13/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "d3a7e17f566a162b02902cbfe8f531ec14ac4d0136c9829f978e34d91a10e1a6"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "14": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "POSTGRES", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "label": "14.24", "major": "14", "channel": "stable", "revision": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897", "source_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897", "catalog_fingerprint": "b272e6a82e4c46efda81c3a6a4cdf7de6a83dfff7f02f226a392fbe9acdd3adb"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://pg.center/docs/14/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 14 English manual", "sha256": "7fd26810ad531d4158f3c87ccf1168c7b4b7b0763441b8912b525d7c20aef658", "language": "en", "original_url": "/docs/14/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">38.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#XFUNC-C-DYNLOAD\">38.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/14/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u904d\u5386\u901a\u5f80\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/14/xfunc-c.html#DFUNC\" title=\"38.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a038.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u9009\u62e9\u5305\u542b\u521d\u59cb\u5316\u548c\u7ec8\u7ed3\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u88c5\u8f7d\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_fini</code> \u7684\u51fd\u6570\uff0c\u8be5\u51fd\u6570\u4f1a\u5728\u6587\u4ef6\u5378\u8f7d\u524d\u7acb\u5373\u88ab\u8c03\u7528\u3002\u540c\u6837\uff0c\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u53c2\u6570\uff0c\u5e76\u4e14\u5e94\u8fd4\u56de void\u3002\u6ce8\u610f\uff0c<code class=\"function\">_PG_fini</code> \u53ea\u4f1a\u5728\u5378\u8f7d\u6587\u4ef6\u65f6\u88ab\u8c03\u7528\uff0c\u800c\u4e0d\u4f1a\u5728\u8fdb\u7a0b\u7ec8\u6b62\u65f6\u88ab\u8c03\u7528\u3002\uff08\u76ee\u524d\uff0c\u5378\u8f7d\u5df2\u88ab\u7981\u7528\uff0c\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\uff0c\u4f46\u5c06\u6765\u53ef\u80fd\u4f1a\u6539\u53d8\u3002\uff09</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#XFUNC-C-BASETYPE\">38.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u5c06\u5b83\u4eec\u4f20\u5165\u51fd\u6570\u548c\u4ece\u51fd\u6570\u4f20\u51fa\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/14/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a038.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a038.2</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/14/xaggr.html\" title=\"38.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a038.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/14/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a038.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a038.2</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a038.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">text</code></td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.7\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#XFUNC-C-V1-CALL-CONV\">38.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy((void *) VARDATA(new_t), /* destination */\n           (void *) VARDATA_ANY(t), /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/14/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"38.10.8.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a038.10.8\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/14/triggers.html\" title=\"\u7b2c\u00a039\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a039\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/14/plhandler.html\" title=\"\u7b2c\u00a056\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a056\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.8\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#XFUNC-C-CODE\">38.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/14/xfunc-c.html#DFUNC\" title=\"38.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a038.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/14/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"38.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a038.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#DFUNC\">38.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 3.0 \u7248\u8d77\u9002\u7528\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">HP-UX</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7cfb\u7edf\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">+z</code>\u3002\u4f7f\u7528 <span class=\"application\">GCC</span> \u65f6\u5219\u662f <code class=\"option\">-fPIC</code>\u3002\u7528\u4e8e\u5171\u4eab\u5e93\u7684\u94fe\u63a5\u5668\u9009\u9879\u662f <code class=\"option\">-b</code>\u3002\u56e0\u6b64\uff1a</p>\n<pre class=\"programlisting\">cc +z -c foo.c\n</pre>\n<p lang=\"zh\">\u6216\u8005\uff1a</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff1a</p>\n<pre class=\"programlisting\">ld -b -o foo.sl foo.o\n</pre>\n<p lang=\"zh\"><span class=\"systemitem\">HP-UX</span> \u4f7f\u7528 <code class=\"filename\">.sl</code> \u4f5c\u4e3a\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff0c\u8fd9\u4e0e\u5927\u591a\u6570\u5176\u4ed6\u7cfb\u7edf\u4e0d\u540c\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/14/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"38.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a038.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.10\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#XFUNC-C-COMPOSITE-TYPE-ARGS\">38.10.6. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u5b8f\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.11\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#XFUNC-C-RETURNING-ROWS\">38.10.7. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#XFUNC-C-RETURN-SET\">38.10.8. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_UINT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.13\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#XFUNC-C-POLYMORPHIC\">38.10.9. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de<a class=\"xref\" href=\"/docs/14/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"38.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a038.2.5\u00a0\u8282</a>\u4e2d\u63cf\u8ff0\u7684\u591a\u6001\u7c7b\u578b\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-SHARED-ADDIN\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#XFUNC-SHARED-ADDIN\">38.10.10. \u5171\u4eab\u5185\u5b58\u4e0e LWLocks</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><span id=\"XFUNC-SHARED-ADDIN-AT-STARTUP\"></span>\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLock \u548c\u4e00\u5757\u5171\u4eab\u5185\u5b58\u3002\u9644\u52a0\u6a21\u5757\u7684\u5171\u4eab\u5e93\u5fc5\u987b\u901a\u8fc7\u5728\u4ee5\u4e0b\u53c2\u6570\u4e2d\u6307\u5b9a\u5b83\u6765\u9884\u88c5\u8f7d\uff1a<a class=\"xref\" href=\"/docs/14/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a><a class=\"indexterm\" id=\"id-1.8.3.13.14.2.3\" name=\"id-1.8.3.13.14.2.3\"></a>\u3002\u5171\u4eab\u5185\u5b58\u53ef\u4ee5\u901a\u8fc7\u4e0b\u9762\u7684\u8c03\u7528\u6765\u9884\u7559\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(int size)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728\u4f60\u7684 <code class=\"function\">_PG_init</code> \u51fd\u6570\u4e2d\u3002</p>\n<p lang=\"zh\">\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8be5\u8c03\u7528\u5e94\u653e\u5728 <code class=\"function\">_PG_init</code> \u4e2d\u3002\u8fd9\u6837\u53ef\u4ee5\u786e\u4fdd\u4e00\u4e2a\u5305\u542b <code class=\"literal\">num_lwlocks</code> \u4e2a LWLock \u7684\u6570\u7ec4\u53ef\u901a\u8fc7\u4ee5\u4e0b\u540d\u79f0\u8bbf\u95ee\uff1a<code class=\"literal\">tranche_name</code>\u3002\u4f7f\u7528 <code class=\"function\">GetNamedLWLockTranche</code> \u53ef\u4ee5\u53d6\u5f97\u6307\u5411\u8be5\u6570\u7ec4\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u6001\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u9644\u52a0\u5230\u5176\u5206\u914d\u7684\u5171\u4eab\u5185\u5b58\u5e76\u8fdb\u884c\u521d\u59cb\u5316\u65f6\uff0c\u90fd\u5e94\u4f7f\u7528\u8f7b\u91cf\u7ea7\u9501 AddinShmemInitLock\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\n\nif (!ptr)\n{\n        bool    found;\n\n        LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\n        ptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\n        if (!found)\n        {\n                initialize contents of shmem area;\n                acquire any requested LWLocks using:\n                ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n        }\n        LWLockRelease(AddinShmemInitLock);\n}\n</pre>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/14/xfunc-c.html#EXTEND-CPP\">38.10.11. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/14/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/14/xfunc-c.html", "method": "same-major semantic node", "sha256": "2fbd11bbae7ab2425c4de4cb1fc3f8b0c29c45b2e6551bb486931806474d2dfe", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/p[10]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[10]/p[2]", "#XFUNC-C/div[10]/p[6]", "#XFUNC-C/div[10]/p[7]", "#XFUNC-C/div[10]/p[8]", "#XFUNC-C/div[11]/div[7]/p[1]", "#XFUNC-C/div[11]/div[8]/p[1]", "#XFUNC-C/div[11]/p[11]", "#XFUNC-C/div[11]/p[13]", "#XFUNC-C/div[11]/p[14]", "#XFUNC-C/div[11]/p[16]", "#XFUNC-C/div[11]/p[18]", "#XFUNC-C/div[11]/p[19]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[21]", "#XFUNC-C/div[11]/p[22]", "#XFUNC-C/div[11]/p[24]", "#XFUNC-C/div[11]/p[25]", "#XFUNC-C/div[11]/p[27]", "#XFUNC-C/div[11]/p[28]", "#XFUNC-C/div[11]/p[3]", "#XFUNC-C/div[11]/p[4]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[9]", "#XFUNC-C/div[12]/div[19]/p[1]", "#XFUNC-C/div[12]/p[10]", "#XFUNC-C/div[12]/p[12]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[15]", "#XFUNC-C/div[12]/p[20]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[26]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[2]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[8]", "#XFUNC-C/div[13]/p[1]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[14]/p[1]", "#XFUNC-C/div[14]/p[3]", "#XFUNC-C/div[14]/p[6]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[15]/p[2]", "#XFUNC-C/div[15]/p[4]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[11]", "#XFUNC-C/div[5]/p[13]", "#XFUNC-C/div[5]/p[18]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[12]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[14]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[4]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[6]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/14/description/0": "dynamically-loaded C functions", "/versions/14/facts/0/label": "Kind", "/versions/14/facts/0/value": "Native function language", "/versions/14/facts/1/label": "Trusted", "/versions/14/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "518949b03459ed9d65aa9ace0a03bdb2d64b5d9e070ef66215a9ef4904368633"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "15": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "POSTGRES", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "label": "15.19", "major": "15", "channel": "stable", "revision": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89", "source_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89", "catalog_fingerprint": "fefe3c425147a86defada190c9b0663cfe02caa1724f5dede93e46457572252d"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://pg.center/docs/15/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 15 English manual", "sha256": "10276a33177d2982a779f16dbbf668edd743381a24cdb1c198ebbf64825209f9", "language": "en", "original_url": "/docs/15/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">38.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#XFUNC-C-DYNLOAD\">38.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/15/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u904d\u5386\u901a\u5f80\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/15/xfunc-c.html#DFUNC\" title=\"38.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a038.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u5305\u542b\u4e00\u4e2a\u521d\u59cb\u5316\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code>\u7684\u51fd\u6570\uff0c\u90a3\u4e2a\u51fd\u6570\u5c06\u5728\u52a0\u8f7d\u6587\u4ef6\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u4efb\u4f55\u53c2\u6570\uff0c\u5e94\u8be5\u8fd4\u56devoid\u3002\u76ee\u524d\u6ca1\u6709\u529e\u6cd5\u5378\u8f7d\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#XFUNC-C-BASETYPE\">38.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u5c06\u5b83\u4eec\u4f20\u5165\u51fd\u6570\u548c\u4ece\u51fd\u6570\u4f20\u51fa\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/15/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a038.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a038.2</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/15/xaggr.html\" title=\"38.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a038.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/15/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a038.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a038.2</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a038.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">text</code></td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.7\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#XFUNC-C-V1-CALL-CONV\">38.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy((void *) VARDATA(new_t), /* destination */\n           (void *) VARDATA_ANY(t), /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/15/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"38.10.8.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a038.10.8\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/15/triggers.html\" title=\"\u7b2c\u00a039\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a039\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/15/plhandler.html\" title=\"\u7b2c\u00a058\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a058\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.8\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#XFUNC-C-CODE\">38.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/15/xfunc-c.html#DFUNC\" title=\"38.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a038.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/15/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"38.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a038.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#DFUNC\">38.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 3.0 \u7248\u8d77\u9002\u7528\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">HP-UX</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7cfb\u7edf\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">+z</code>\u3002\u4f7f\u7528 <span class=\"application\">GCC</span> \u65f6\u5219\u662f <code class=\"option\">-fPIC</code>\u3002\u7528\u4e8e\u5171\u4eab\u5e93\u7684\u94fe\u63a5\u5668\u9009\u9879\u662f <code class=\"option\">-b</code>\u3002\u56e0\u6b64\uff1a</p>\n<pre class=\"programlisting\">cc +z -c foo.c\n</pre>\n<p lang=\"zh\">\u6216\u8005\uff1a</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff1a</p>\n<pre class=\"programlisting\">ld -b -o foo.sl foo.o\n</pre>\n<p lang=\"zh\"><span class=\"systemitem\">HP-UX</span> \u4f7f\u7528 <code class=\"filename\">.sl</code> \u4f5c\u4e3a\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff0c\u8fd9\u4e0e\u5927\u591a\u6570\u5176\u4ed6\u7cfb\u7edf\u4e0d\u540c\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/15/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"38.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a038.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.10\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#XFUNC-C-COMPOSITE-TYPE-ARGS\">38.10.6. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u5b8f\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.11\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#XFUNC-C-RETURNING-ROWS\">38.10.7. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#XFUNC-C-RETURN-SET\">38.10.8. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_INT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"id-1.8.3.13.13\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#XFUNC-C-POLYMORPHIC\">38.10.9. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de<a class=\"xref\" href=\"/docs/15/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"38.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a038.2.5\u00a0\u8282</a>\u4e2d\u63cf\u8ff0\u7684\u591a\u6001\u7c7b\u578b\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-SHARED-ADDIN\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#XFUNC-SHARED-ADDIN\">38.10.10. \u5171\u4eab\u5185\u5b58\u4e0e LWLocks</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLocks \u548c\u5171\u4eab\u5185\u5b58\u3002\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\u3002\u5171\u4eab\u5e93\u5e94\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\uff0c\u518d\u7531\u6b64\u94a9\u5b50\u9884\u7559 LWLocks \u6216\u5171\u4eab\u5185\u5b58\u3002\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u8c03\u7528\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(int size)\n</pre>\n<p lang=\"zh\">\u5728 shmem_request_hook \u4e2d\u8c03\u7528\u3002</p>\n<p lang=\"zh\">\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u5728 shmem_request_hook \u4e2d\u8c03\u7528\u3002\u8fd9\u5c06\u786e\u4fdd\u5b58\u5728\u4e00\u4e2a\u540d\u4e3a tranche_name\u3001\u5305\u542b num_lwlocks \u4e2a LWLocks \u7684\u6570\u7ec4\u3002\u4f7f\u7528 GetNamedLWLockTranche \u83b7\u53d6\u8be5\u6570\u7ec4\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\">PostgreSQL \u6e90\u7801\u6811\u7684 contrib/pg_stat_statements/pg_stat_statements.c \u4e2d\u63d0\u4f9b\u4e86 shmem_request_hook \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u6001\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u9644\u52a0\u5230\u5176\u5206\u914d\u7684\u5171\u4eab\u5185\u5b58\u5e76\u8fdb\u884c\u521d\u59cb\u5316\u65f6\uff0c\u90fd\u5e94\u4f7f\u7528\u8f7b\u91cf\u7ea7\u9501 AddinShmemInitLock\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\n\nif (!ptr)\n{\n        bool    found;\n\n        LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\n        ptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\n        if (!found)\n        {\n                initialize contents of shmem area;\n                acquire any requested LWLocks using:\n                ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n        }\n        LWLockRelease(AddinShmemInitLock);\n}\n</pre>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/15/xfunc-c.html#EXTEND-CPP\">38.10.11. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/15/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/15/xfunc-c.html", "method": "same-major semantic node", "sha256": "525a67d45851e1ac7a414aeb9e309bc6f6ccd6c93cc6c70954c06bdb0e5279bd", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/p[10]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[10]/p[2]", "#XFUNC-C/div[10]/p[6]", "#XFUNC-C/div[10]/p[7]", "#XFUNC-C/div[10]/p[8]", "#XFUNC-C/div[11]/div[7]/p[1]", "#XFUNC-C/div[11]/div[8]/p[1]", "#XFUNC-C/div[11]/p[11]", "#XFUNC-C/div[11]/p[13]", "#XFUNC-C/div[11]/p[14]", "#XFUNC-C/div[11]/p[16]", "#XFUNC-C/div[11]/p[18]", "#XFUNC-C/div[11]/p[19]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[21]", "#XFUNC-C/div[11]/p[22]", "#XFUNC-C/div[11]/p[24]", "#XFUNC-C/div[11]/p[25]", "#XFUNC-C/div[11]/p[27]", "#XFUNC-C/div[11]/p[28]", "#XFUNC-C/div[11]/p[3]", "#XFUNC-C/div[11]/p[4]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[9]", "#XFUNC-C/div[12]/div[19]/p[1]", "#XFUNC-C/div[12]/p[10]", "#XFUNC-C/div[12]/p[12]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[15]", "#XFUNC-C/div[12]/p[20]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[26]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[2]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[8]", "#XFUNC-C/div[13]/p[1]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[15]/p[2]", "#XFUNC-C/div[15]/p[4]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[11]", "#XFUNC-C/div[5]/p[13]", "#XFUNC-C/div[5]/p[16]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[12]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[14]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[13]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[4]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[6]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/15/description/0": "dynamically-loaded C functions", "/versions/15/facts/0/label": "Kind", "/versions/15/facts/0/value": "Native function language", "/versions/15/facts/1/label": "Trusted", "/versions/15/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "68345e2c267c4123cad990fecd8e72ab97acab1641065493d77ea3ebb1428a9f"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "16": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "POSTGRES", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "label": "16.15", "major": "16", "channel": "stable", "revision": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed", "source_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed", "catalog_fingerprint": "fa133458dc8f52e15083b4f59b7a582e2e378b608d3ac5c53054df458a374e23"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://pg.center/docs/16/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 16 English manual", "sha256": "547b842b9f6cd0824cd1cefa54c55a311c5993d9b643cb58a7e73f53ae18dcb5", "language": "en", "original_url": "/docs/16/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">38.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#XFUNC-C-DYNLOAD\">38.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/16/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u904d\u5386\u901a\u5f80\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/16/xfunc-c.html#DFUNC\" title=\"38.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a038.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u5305\u542b\u4e00\u4e2a\u521d\u59cb\u5316\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code>\u7684\u51fd\u6570\uff0c\u90a3\u4e2a\u51fd\u6570\u5c06\u5728\u52a0\u8f7d\u6587\u4ef6\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u4efb\u4f55\u53c2\u6570\uff0c\u5e94\u8be5\u8fd4\u56devoid\u3002\u76ee\u524d\u6ca1\u6709\u529e\u6cd5\u5378\u8f7d\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#XFUNC-C-BASETYPE\">38.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u5c06\u5b83\u4eec\u4f20\u5165\u51fd\u6570\u548c\u4ece\u51fd\u6570\u4f20\u51fa\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/16/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a038.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a038.2</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/16/xaggr.html\" title=\"38.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a038.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/16/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a038.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a038.2</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a038.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td lang=\"zh\">\u6587\u672c</td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-V1-CALL-CONV\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#XFUNC-C-V1-CALL-CONV\">38.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n#include \"varatt.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy(VARDATA(new_t),          /* destination */\n           VARDATA_ANY(t),          /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/16/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"38.10.8.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a038.10.8\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/16/triggers.html\" title=\"\u7b2c\u00a039\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a039\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/16/plhandler.html\" title=\"\u7b2c\u00a058\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a058\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-CODE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#XFUNC-C-CODE\">38.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/16/xfunc-c.html#DFUNC\" title=\"38.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a038.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/16/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"38.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a038.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#DFUNC\">38.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 3.0 \u7248\u8d77\u9002\u7528\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/16/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"38.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a038.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-COMPOSITE-TYPE-ARGS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#XFUNC-C-COMPOSITE-TYPE-ARGS\">38.10.6. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u51fd\u6570\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURNING-ROWS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#XFUNC-C-RETURNING-ROWS\">38.10.7. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#XFUNC-C-RETURN-SET\">38.10.8. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_INT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-POLYMORPHIC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#XFUNC-C-POLYMORPHIC\">38.10.9. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de<a class=\"xref\" href=\"/docs/16/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"38.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a038.2.5\u00a0\u8282</a>\u4e2d\u63cf\u8ff0\u7684\u591a\u6001\u7c7b\u578b\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-SHARED-ADDIN\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#XFUNC-SHARED-ADDIN\">38.10.10. \u5171\u4eab\u5185\u5b58\u4e0e LWLocks</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLocks \u548c\u5171\u4eab\u5185\u5b58\u3002\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\u3002\u5171\u4eab\u5e93\u5e94\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\uff0c\u518d\u7531\u6b64\u94a9\u5b50\u9884\u7559 LWLocks \u6216\u5171\u4eab\u5185\u5b58\u3002\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u8c03\u7528\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(int size)\n</pre>\n<p lang=\"zh\">\u5728 shmem_request_hook \u4e2d\u8c03\u7528\u3002</p>\n<p lang=\"zh\">\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u5728 shmem_request_hook \u4e2d\u8c03\u7528\u3002\u8fd9\u5c06\u786e\u4fdd\u5b58\u5728\u4e00\u4e2a\u540d\u4e3a tranche_name\u3001\u5305\u542b num_lwlocks \u4e2a LWLocks \u7684\u6570\u7ec4\u3002\u4f7f\u7528 GetNamedLWLockTranche \u83b7\u53d6\u8be5\u6570\u7ec4\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\">PostgreSQL \u6e90\u7801\u6811\u7684 contrib/pg_stat_statements/pg_stat_statements.c \u4e2d\u63d0\u4f9b\u4e86 shmem_request_hook \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u6001\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u9644\u52a0\u5230\u5176\u5206\u914d\u7684\u5171\u4eab\u5185\u5b58\u5e76\u8fdb\u884c\u521d\u59cb\u5316\u65f6\uff0c\u90fd\u5e94\u4f7f\u7528\u8f7b\u91cf\u7ea7\u9501 AddinShmemInitLock\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\n\nif (!ptr)\n{\n        bool    found;\n\n        LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\n        ptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\n        if (!found)\n        {\n                initialize contents of shmem area;\n                acquire any requested LWLocks using:\n                ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n        }\n        LWLockRelease(AddinShmemInitLock);\n}\n</pre>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/16/xfunc-c.html#EXTEND-CPP\">38.10.11. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/16/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/16/protocol-overview.html", "method": "same-major semantic node", "sha256": "44bc52e9e7ea6a128300584836e839d6a6b6b161cadff330571034de65b26ac1", "language": "zh", "matched_nodes": ["#PROTOCOL-OVERVIEW/div[9]/p[1]/span[2]/span[0]"]}, {"url": "/docs/16/xfunc-c.html", "method": "same-major semantic node", "sha256": "8809acadf9ad2b1e79b23f2446b430168f986eaa6d17e9b2e887266bb462299e", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/p[10]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[10]/p[2]", "#XFUNC-C/div[10]/p[6]", "#XFUNC-C/div[10]/p[7]", "#XFUNC-C/div[10]/p[8]", "#XFUNC-C/div[11]/div[7]/p[1]", "#XFUNC-C/div[11]/div[8]/p[1]", "#XFUNC-C/div[11]/p[11]", "#XFUNC-C/div[11]/p[13]", "#XFUNC-C/div[11]/p[14]", "#XFUNC-C/div[11]/p[16]", "#XFUNC-C/div[11]/p[18]", "#XFUNC-C/div[11]/p[19]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[21]", "#XFUNC-C/div[11]/p[22]", "#XFUNC-C/div[11]/p[24]", "#XFUNC-C/div[11]/p[25]", "#XFUNC-C/div[11]/p[27]", "#XFUNC-C/div[11]/p[28]", "#XFUNC-C/div[11]/p[3]", "#XFUNC-C/div[11]/p[4]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[9]", "#XFUNC-C/div[12]/div[19]/p[1]", "#XFUNC-C/div[12]/p[10]", "#XFUNC-C/div[12]/p[12]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[15]", "#XFUNC-C/div[12]/p[20]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[26]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[2]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[8]", "#XFUNC-C/div[13]/p[1]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[15]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[15]/p[2]", "#XFUNC-C/div[15]/p[4]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[11]", "#XFUNC-C/div[5]/p[13]", "#XFUNC-C/div[5]/p[16]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[12]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[14]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/16/description/0": "dynamically-loaded C functions", "/versions/16/facts/0/label": "Kind", "/versions/16/facts/0/value": "Native function language", "/versions/16/facts/1/label": "Trusted", "/versions/16/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "a08f9d03645bd07ce9e081c80f8b1cda3a561234d5b16add71b3637b83140ff1"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "17": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "POSTGRES", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "label": "17.11", "major": "17", "channel": "stable", "revision": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979", "source_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979", "catalog_fingerprint": "4bbe3ac77becd618478f66aec420a533e9017be356c5c1d51a4b17f0fd497c07"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://pg.center/docs/17/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 17 English manual", "sha256": "e0e63458d9e41ad4fe16477a4638b8d9032900de922284de8f36c2b6779b5c3f", "language": "en", "original_url": "/docs/17/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">36.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-C-DYNLOAD\">36.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/17/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u904d\u5386\u901a\u5f80\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/17/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u5305\u542b\u4e00\u4e2a\u521d\u59cb\u5316\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code>\u7684\u51fd\u6570\uff0c\u90a3\u4e2a\u51fd\u6570\u5c06\u5728\u52a0\u8f7d\u6587\u4ef6\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u4efb\u4f55\u53c2\u6570\uff0c\u5e94\u8be5\u8fd4\u56devoid\u3002\u76ee\u524d\u6ca1\u6709\u529e\u6cd5\u5378\u8f7d\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-C-BASETYPE\">36.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u5c06\u5b83\u4eec\u4f20\u5165\u51fd\u6570\u548c\u4ece\u51fd\u6570\u4f20\u51fa\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/17/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/17/xaggr.html\" title=\"36.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a036.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/17/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td lang=\"zh\">\u6587\u672c</td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-V1-CALL-CONV\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-C-V1-CALL-CONV\">36.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n#include \"varatt.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy(VARDATA(new_t),          /* destination */\n           VARDATA_ANY(t),          /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/17/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"36.10.8.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a036.10.8\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/17/triggers.html\" title=\"\u7b2c\u00a037\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a037\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/17/plhandler.html\" title=\"\u7b2c\u00a056\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a056\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-CODE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-C-CODE\">36.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/17/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/17/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#DFUNC\">36.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 13.0 \u8d77\u9002\u7528\uff1b\u66f4\u65e9\u7248\u672c\u4f7f\u7528\u7684\u662f <code class=\"filename\">gcc</code> \u7f16\u8bd1\u5668\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/17/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-COMPOSITE-TYPE-ARGS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-C-COMPOSITE-TYPE-ARGS\">36.10.6. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u51fd\u6570\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURNING-ROWS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-C-RETURNING-ROWS\">36.10.7. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-C-RETURN-SET\">36.10.8. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_INT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-POLYMORPHIC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-C-POLYMORPHIC\">36.10.9. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de<a class=\"xref\" href=\"/docs/17/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"36.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a036.2.5\u00a0\u8282</a>\u4e2d\u63cf\u8ff0\u7684\u591a\u6001\u7c7b\u578b\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-SHARED-ADDIN\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-SHARED-ADDIN\">36.10.10. \u5171\u4eab\u5185\u5b58</a></span></h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.10.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u3002\u4e3a\u6b64\uff0c\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\uff0c\u5e76\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\u3002\u6b64\u94a9\u5b50\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559\u5171\u4eab\u5185\u5b58\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(Size size)\n</pre>\n<p lang=\"zh\">\u6765\u9884\u7559\u5171\u4eab\u5185\u5b58\u3002\u6bcf\u4e2a\u540e\u7aef\u90fd\u5e94\u5f53\u901a\u8fc7\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">void *ShmemInitStruct(const char *name, Size size, bool *foundPtr)\n</pre>\n<p lang=\"zh\">\u6765\u83b7\u53d6\u6307\u5411\u8fd9\u5757\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u6307\u9488\u3002\u5982\u679c\u8be5\u51fd\u6570\u628a <code class=\"literal\">foundPtr</code> \u8bbe\u4e3a <code class=\"literal\">false</code>\uff0c\u8c03\u7528\u8005\u5c31\u5e94\u521d\u59cb\u5316\u8fd9\u5757\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u5185\u5bb9\uff1b\u5982\u679c <code class=\"literal\">foundPtr</code> \u4e3a <code class=\"literal\">true</code>\uff0c\u8bf4\u660e\u8be5\u5171\u4eab\u5185\u5b58\u5df2\u7ecf\u7531\u5176\u4ed6\u540e\u7aef\u521d\u59cb\u5316\u8fc7\uff0c\u8c03\u7528\u8005\u65e0\u9700\u518d\u505a\u521d\u59cb\u5316\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u4e89\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u521d\u59cb\u5316\u5176\u5171\u4eab\u5185\u5b58\u5206\u914d\u65f6\u90fd\u5e94\u4f7f\u7528 LWLock <code class=\"function\">AddinShmemInitLock</code>\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\nbool        found;\n\nLWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\nptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\nif (!found)\n{\n    ... initialize contents of shared memory ...\n    ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n}\nLWLockRelease(AddinShmemInitLock);\n</pre>\n<p lang=\"zh\"><code class=\"literal\">shmem_startup_hook</code> \u4e3a\u521d\u59cb\u5316\u4ee3\u7801\u63d0\u4f9b\u4e86\u4e00\u4e2a\u65b9\u4fbf\u7684\u4f4d\u7f6e\uff0c\u4f46\u5e76\u4e0d\u5f3a\u5236\u8981\u6c42\u6240\u6709\u8fd9\u7c7b\u4ee3\u7801\u90fd\u653e\u5728\u8fd9\u4e2a\u94a9\u5b50\u4e2d\u3002\u5728 Windows \u4e0a\uff08\u4ee5\u53ca\u4efb\u4f55\u5b9a\u4e49\u4e86 <code class=\"literal\">EXEC_BACKEND</code> \u7684\u5e73\u53f0\u4e0a\uff09\uff0c\u6bcf\u4e2a\u540e\u7aef\u90fd\u4f1a\u5728\u9644\u52a0\u5230\u5171\u4eab\u5185\u5b58\u540e\u4e0d\u4e45\u6267\u884c\u5df2\u6ce8\u518c\u7684 <code class=\"literal\">shmem_startup_hook</code>\uff0c\u56e0\u6b64\u63d2\u4ef6\u5728\u8be5\u94a9\u5b50\u4e2d\u4ecd\u5e94\u50cf\u4e0a\u4f8b\u90a3\u6837\u83b7\u53d6 <code class=\"function\">AddinShmemInitLock</code>\u3002\u5728\u5176\u4ed6\u5e73\u53f0\u4e0a\uff0c\u53ea\u6709 postmaster \u8fdb\u7a0b\u4f1a\u6267\u884c <code class=\"literal\">shmem_startup_hook</code>\uff0c\u6bcf\u4e2a\u540e\u7aef\u4f1a\u81ea\u52a8\u7ee7\u627f\u8fd9\u4e9b\u5171\u4eab\u5185\u5b58\u6307\u9488\u3002</p>\n<p lang=\"zh\"><code class=\"literal\">shmem_request_hook</code> \u4e0e <code class=\"literal\">shmem_startup_hook</code> \u7684\u4e00\u4e2a\u5b8c\u6574\u793a\u4f8b\u53ef\u89c1\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_stat_statements/pg_stat_statements.c</code>\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.10.2.\u00a0\u542f\u52a8\u540e\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u4e4b\u540e\uff0c\u5e76\u4e14\u65e0\u9700\u501f\u52a9 <code class=\"literal\">shmem_request_hook</code> \u6765\u5b8c\u6210\u3002\u4e3a\u6b64\uff0c\u6bcf\u4e2a\u9700\u8981\u4f7f\u7528\u8be5\u5171\u4eab\u5185\u5b58\u7684\u540e\u7aef\u90fd\u5e94\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u83b7\u53d6\u4e00\u4e2a\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">void *GetNamedDSMSegment(const char *name, size_t size,\n                         void (*init_callback) (void *ptr),\n                         bool *found)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u7ed9\u5b9a\u540d\u79f0\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u5c1a\u4e0d\u5b58\u5728\uff0c\u8be5\u51fd\u6570\u4f1a\u5206\u914d\u8be5\u6bb5\uff0c\u5e76\u4f7f\u7528\u63d0\u4f9b\u7684 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u5bf9\u5176\u8fdb\u884c\u521d\u59cb\u5316\u3002\u5982\u679c\u8be5\u6bb5\u5df2\u7ecf\u7531\u53e6\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8fc7\uff0c\u8be5\u51fd\u6570\u5c31\u53ea\u4f1a\u628a\u73b0\u6709\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u9644\u52a0\u5230\u5f53\u524d\u540e\u7aef\u3002</p>\n<p lang=\"zh\">\u4e0e\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559\u7684\u5171\u4eab\u5185\u5b58\u4e0d\u540c\uff0c\u4f7f\u7528 GetNamedDSMSegment \u9884\u7559\u5171\u4eab\u5185\u5b58\u65f6\uff0c\u65e0\u9700\u83b7\u53d6 AddinShmemInitLock\uff0c\u4e5f\u65e0\u9700\u91c7\u53d6\u5176\u4ed6\u63aa\u65bd\u907f\u514d\u7ade\u6001\u6761\u4ef6\u3002\u6b64\u51fd\u6570\u4fdd\u8bc1\u4ec5\u7531\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8be5\u6bb5\uff0c\u5176\u4ed6\u6240\u6709\u540e\u7aef\u83b7\u5f97\u7684\u90fd\u662f\u6307\u5411\u5df2\u5b8c\u5168\u5206\u914d\u5e76\u521d\u59cb\u5316\u7684\u6bb5\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\"><code class=\"function\">GetNamedDSMSegment</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/test_dsm_registry/test_dsm_registry.c</code>\uff0c\u4f4d\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-LWLOCKS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\">36.10.11. \u8f7b\u91cf\u7ea7\u9501\uff08LWLocks\uff09</h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLocks\u3002\u4e0e\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u4e00\u6837\uff0c\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\uff0c\u5e76\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\u3002\u6b64\u94a9\u5b50\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8fd9\u786e\u4fdd\u5b58\u5728\u4e00\u4e2a\u540d\u4e3a tranche_name\u3001\u5305\u542b num_lwlocks \u4e2a LWLocks \u7684\u6570\u7ec4\u3002\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u53d6\u5f97\u8be5\u6570\u7ec4\u7684\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">LWLockPadded *GetNamedLWLockTranche(const char *tranche_name)\n</pre>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.2.\u00a0\u542f\u52a8\u540e\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u83b7\u53d6 LWLocks \u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u540e\u8fdb\u884c\uff0c\u4e5f\u65e0\u9700\u501f\u52a9 <code class=\"literal\">shmem_request_hook</code>\u3002\u4e3a\u6b64\uff0c\u9996\u5148\u901a\u8fc7\u8c03\u7528\u4e0b\u9762\u7684\u51fd\u6570\u5206\u914d\u4e00\u4e2a <code class=\"literal\">tranche_id</code>\uff1a</p>\n<pre class=\"programlisting\">int LWLockNewTrancheId(void)\n</pre>\n<p lang=\"zh\">\u63a5\u4e0b\u6765\uff0c\u521d\u59cb\u5316\u6bcf\u4e2a LWLock\uff0c\u5e76\u628a\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\uff1a</p>\n<pre class=\"programlisting\">void LWLockInitialize(LWLock *lock, int tranche_id)\n</pre>\n<p lang=\"zh\">\u4e0e\u5171\u4eab\u5185\u5b58\u7c7b\u4f3c\uff0c\u6bcf\u4e2a\u540e\u7aef\u90fd\u5e94\u786e\u4fdd\u53ea\u6709\u4e00\u4e2a\u8fdb\u7a0b\u4f1a\u5206\u914d\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u5e76\u521d\u59cb\u5316\u6bcf\u4e00\u4e2a\u65b0\u7684 LWLock\u3002\u4e00\u79cd\u505a\u6cd5\u662f\u4ec5\u5728\u6301\u6709 <code class=\"function\">AddinShmemInitLock</code> \u72ec\u5360\u9501\u7684\u5171\u4eab\u5185\u5b58\u521d\u59cb\u5316\u4ee3\u7801\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u3002\u5982\u679c\u4f7f\u7528 <code class=\"function\">GetNamedDSMSegment</code>\uff0c\u90a3\u4e48\u5728 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u5c31\u8db3\u4ee5\u907f\u514d\u7ade\u4e89\u6761\u4ef6\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6bcf\u4e2a\u4f7f\u7528\u8be5 <code class=\"literal\">tranche_id</code> \u7684\u540e\u7aef\u90fd\u5e94\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u628a\u5b83\u4e0e\u4e00\u4e2a <code class=\"literal\">tranche_name</code> \u5173\u8054\u8d77\u6765\uff1a</p>\n<pre class=\"programlisting\">void LWLockRegisterTranche(int tranche_id, const char *tranche_name)\n</pre>\n<p lang=\"zh\"><code class=\"function\">LWLockNewTrancheId</code>\u3001<code class=\"function\">LWLockInitialize</code> \u548c <code class=\"function\">LWLockRegisterTranche</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_prewarm/autoprewarm.c</code>\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-WAIT-EVENTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-ADDIN-WAIT-EVENTS\">36.10.12. \u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u5728\u7b49\u5f85\u4e8b\u4ef6\u7c7b\u578b <code class=\"literal\">Extension</code> \u4e0b\u5b9a\u4e49\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\uff1a</p>\n<pre class=\"programlisting\">uint32 WaitEventExtensionNew(const char *wait_event_name)\n</pre>\n<p lang=\"zh\">\u8be5\u7b49\u5f85\u4e8b\u4ef6\u4f1a\u5173\u8054\u5230\u4e00\u4e2a\u9762\u5411\u7528\u6237\u7684\u81ea\u5b9a\u4e49\u5b57\u7b26\u4e32\u3002\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/worker_spi</code>\uff0c\u4f4d\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n<p lang=\"zh\">\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\u53ef\u4ee5\u5728 <a class=\"link\" href=\"/docs/17/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW\" title=\"27.2.3.\u00a0pg_stat_activity\"><code class=\"structname\">pg_stat_activity</code></a> \u4e2d\u67e5\u770b\uff1a</p>\n<pre class=\"screen\">=# SELECT wait_event_type, wait_event FROM pg_stat_activity\n     WHERE backend_type ~ 'worker_spi';\n wait_event_type |  wait_event\n-----------------+---------------\n Extension       | WorkerSpiMain\n(1 row)\n</pre>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-INJECTION-POINTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#XFUNC-ADDIN-INJECTION-POINTS\">36.10.13. \u6ce8\u5165\u70b9</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7ed9\u5b9a\u540d\u79f0 <code class=\"literal\">name</code> \u7684\u6ce8\u5165\u70b9\u53ef\u901a\u8fc7\u4ee5\u4e0b\u5b8f\u58f0\u660e\uff1a</p>\n<pre class=\"programlisting\">INJECTION_POINT(name);\n</pre>\n<p lang=\"zh\">\u670d\u52a1\u5668\u4ee3\u7801\u4e2d\u5df2\u7ecf\u5728\u82e5\u5e72\u5173\u952e\u4f4d\u7f6e\u58f0\u660e\u4e86\u6ce8\u5165\u70b9\u3002\u65b0\u589e\u6ce8\u5165\u70b9\u540e\uff0c\u9700\u8981\u91cd\u65b0\u7f16\u8bd1\u4ee3\u7801\uff0c\u624d\u80fd\u8ba9\u8be5\u6ce8\u5165\u70b9\u51fa\u73b0\u5728\u4e8c\u8fdb\u5236\u6587\u4ef6\u4e2d\u3002\u7528 C \u8bed\u8a00\u7f16\u5199\u7684\u63d2\u4ef6\u4e5f\u53ef\u4ee5\u4f7f\u7528\u540c\u4e00\u4e2a\u5b8f\u5728\u81ea\u5df1\u7684\u4ee3\u7801\u4e2d\u58f0\u660e\u6ce8\u5165\u70b9\u3002\u6ce8\u5165\u70b9\u540d\u79f0\u5e94\u4f7f\u7528\u5c0f\u5199\u5b57\u6bcd\uff0c\u5e76\u7528\u8fde\u5b57\u7b26\u5206\u9694\u5404\u4e2a\u672f\u8bed\u3002</p>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u4e3a\u4e00\u4e2a\u5df2\u7ecf\u58f0\u660e\u597d\u7684\u6ce8\u5165\u70b9\u9644\u52a0\u56de\u8c03\uff1a</p>\n<pre class=\"programlisting\">extern void InjectionPointAttach(const char *name,\n                                 const char *library,\n                                 const char *function,\n                                 const void *private_data,\n                                 int private_data_size);\n</pre>\n<p lang=\"zh\">name \u662f\u6ce8\u5165\u70b9\u7684\u540d\u79f0\uff1b\u6267\u884c\u5230\u8fbe\u6b64\u6ce8\u5165\u70b9\u65f6\uff0c\u5c06\u6267\u884c\u4ece library \u52a0\u8f7d\u7684\u51fd\u6570\u3002private_data \u662f\u4e00\u5757\u5927\u5c0f\u4e3a private_data_size \u7684\u79c1\u6709\u6570\u636e\u533a\u57df\uff0c\u5728\u6267\u884c\u56de\u8c03\u65f6\u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a <code class=\"literal\">InjectionPointCallback</code> \u7684\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">static void\ncustom_injection_callback(const char *name, const void *private_data)\n{\n    uint32 wait_event_info = WaitEventInjectionPointNew(name);\n\n    pgstat_report_wait_start(wait_event_info);\n    elog(NOTICE, \"%s: executed custom callback\", name);\n    pgstat_report_wait_end();\n}\n</pre>\n<p lang=\"zh\">\u8fd9\u4e2a\u56de\u8c03\u4f1a\u4ee5 <code class=\"literal\">NOTICE</code> \u7ea7\u522b\u5411\u670d\u52a1\u5668\u9519\u8bef\u65e5\u5fd7\u5199\u5165\u4e00\u6761\u6d88\u606f\uff0c\u4f46\u56de\u8c03\u5b8c\u5168\u53ef\u4ee5\u5b9e\u73b0\u66f4\u590d\u6742\u7684\u903b\u8f91\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u89e3\u9664\u4e00\u4e2a\u6ce8\u5165\u70b9\uff1a</p>\n<pre class=\"programlisting\">extern bool InjectionPointDetach(const char *name);\n</pre>\n<p lang=\"zh\">\u6210\u529f\u65f6\u8fd4\u56de <code class=\"literal\">true</code>\uff0c\u5426\u5219\u8fd4\u56de <code class=\"literal\">false</code>\u3002</p>\n<p lang=\"zh\">\u4e00\u4e2a\u9644\u52a0\u5230\u6ce8\u5165\u70b9\u7684\u56de\u8c03\u4f1a\u5728\u6240\u6709\u540e\u7aef\u4e2d\u751f\u6548\uff0c\u5305\u62ec\u5728\u8c03\u7528 <code class=\"literal\">InjectionPointAttach</code> \u4e4b\u540e\u624d\u542f\u52a8\u7684\u540e\u7aef\u3002\u5b83\u4f1a\u4e00\u76f4\u4fdd\u6301\u9644\u52a0\u72b6\u6001\uff0c\u76f4\u5230\u670d\u52a1\u5668\u505c\u6b62\uff0c\u6216\u8005\u901a\u8fc7 <code class=\"literal\">InjectionPointDetach</code> \u5c06\u5176\u89e3\u9664\u3002</p>\n<p lang=\"zh\">\u76f8\u5173\u793a\u4f8b\u53ef\u89c1\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">src/test/modules/injection_points</code>\u3002</p>\n<p lang=\"zh\">\u8981\u542f\u7528\u6ce8\u5165\u70b9\uff0c\u4f7f\u7528 configure \u65f6\u9700\u6307\u5b9a --enable-injection-points\uff0c\u4f7f\u7528 Meson \u65f6\u9700\u6307\u5b9a -Dinjection_points=true\u3002</p>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/17/xfunc-c.html#EXTEND-CPP\">36.10.14. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/17/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/17/protocol-overview.html", "method": "same-major semantic node", "sha256": "de94711d992bef74aad52fe8a723d81aa9b37a606d96b711bf9faa999a7bb3f5", "language": "zh", "matched_nodes": ["#PROTOCOL-OVERVIEW/div[9]/p[1]/span[2]/span[0]"]}, {"url": "/docs/17/xfunc-c.html", "method": "same-major semantic node", "sha256": "990e09637f0fb7a154eb0f5e8cb7b319a7603214d08975bd973130527b705f1f", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/p[10]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[10]/p[2]", "#XFUNC-C/div[10]/p[6]", "#XFUNC-C/div[10]/p[7]", "#XFUNC-C/div[10]/p[8]", "#XFUNC-C/div[11]/div[7]/p[1]", "#XFUNC-C/div[11]/div[8]/p[1]", "#XFUNC-C/div[11]/p[11]", "#XFUNC-C/div[11]/p[13]", "#XFUNC-C/div[11]/p[14]", "#XFUNC-C/div[11]/p[16]", "#XFUNC-C/div[11]/p[18]", "#XFUNC-C/div[11]/p[19]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[21]", "#XFUNC-C/div[11]/p[22]", "#XFUNC-C/div[11]/p[24]", "#XFUNC-C/div[11]/p[25]", "#XFUNC-C/div[11]/p[27]", "#XFUNC-C/div[11]/p[28]", "#XFUNC-C/div[11]/p[3]", "#XFUNC-C/div[11]/p[4]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[9]", "#XFUNC-C/div[12]/div[19]/p[1]", "#XFUNC-C/div[12]/p[10]", "#XFUNC-C/div[12]/p[12]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[15]", "#XFUNC-C/div[12]/p[20]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[26]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[2]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[8]", "#XFUNC-C/div[13]/p[1]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[14]/div[1]/div[0]", "#XFUNC-C/div[14]/div[1]/p[3]", "#XFUNC-C/div[14]/div[1]/p[5]", "#XFUNC-C/div[14]/div[1]/p[6]", "#XFUNC-C/div[14]/div[1]/p[8]", "#XFUNC-C/div[14]/div[1]/p[9]", "#XFUNC-C/div[14]/div[2]/div[0]", "#XFUNC-C/div[14]/div[2]/p[1]", "#XFUNC-C/div[14]/div[2]/p[3]", "#XFUNC-C/div[14]/div[2]/p[5]", "#XFUNC-C/div[15]/div[1]/div[0]", "#XFUNC-C/div[15]/div[2]/div[0]", "#XFUNC-C/div[15]/div[2]/p[1]", "#XFUNC-C/div[15]/div[2]/p[3]", "#XFUNC-C/div[15]/div[2]/p[5]", "#XFUNC-C/div[15]/div[2]/p[6]", "#XFUNC-C/div[15]/div[2]/p[8]", "#XFUNC-C/div[16]/p[1]", "#XFUNC-C/div[16]/p[3]", "#XFUNC-C/div[16]/p[4]", "#XFUNC-C/div[17]/p[10]", "#XFUNC-C/div[17]/p[12]", "#XFUNC-C/div[17]/p[13]", "#XFUNC-C/div[17]/p[14]", "#XFUNC-C/div[17]/p[1]", "#XFUNC-C/div[17]/p[3]", "#XFUNC-C/div[17]/p[4]", "#XFUNC-C/div[17]/p[7]", "#XFUNC-C/div[17]/p[9]", "#XFUNC-C/div[18]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[18]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[18]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[18]/p[2]", "#XFUNC-C/div[18]/p[4]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[11]", "#XFUNC-C/div[1]/dl[0]/dt[12]", "#XFUNC-C/div[1]/dl[0]/dt[13]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[11]", "#XFUNC-C/div[5]/p[13]", "#XFUNC-C/div[5]/p[16]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[12]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[14]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/17/description/0": "dynamically-loaded C functions", "/versions/17/facts/0/label": "Kind", "/versions/17/facts/0/value": "Native function language", "/versions/17/facts/1/label": "Trusted", "/versions/17/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "2c3890fb4f955e74b41376d7aa8a6d9ec77b0b73f577f6ef0c1f7ed78f388cb1"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "18": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "POSTGRES", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "catalog_fingerprint": "65c93d6048ef30e61023a84f9680fa6a92b1c383b7eb226741170077eb078502"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://pg.center/docs/18/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 18 English manual", "sha256": "d60592edc11f3240b19cecee91523a9a31f1caf68809fa7a39376360d957d68b", "language": "en", "original_url": "/docs/18/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">36.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-DYNLOAD\">36.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/18/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u904d\u5386\u901a\u5f80\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC_EXT(<em class=\"replaceable\"><code>parameters</code></em>);\n</pre>\n<p lang=\"zh\"><code class=\"literal\">PG_MODULE_MAGIC_EXT</code> \u8fd9\u79cd\u5f62\u5f0f\u5141\u8bb8\u4e3a\u6a21\u5757\u6307\u5b9a\u9644\u52a0\u4fe1\u606f\uff1b\u76ee\u524d\u53ef\u4ee5\u6dfb\u52a0\u540d\u79f0\u548c/\u6216\u7248\u672c\u5b57\u7b26\u4e32\u3002\uff08\u5c06\u6765\u53ef\u80fd\u5141\u8bb8\u66f4\u591a\u5b57\u6bb5\u3002\uff09\u53ef\u4ee5\u5199\u6210\u8fd9\u6837\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC_EXT(\n    .name = \"my_module_name\",\n    .version = \"1.2.3\"\n);\n</pre>\n<p lang=\"zh\">\u4e4b\u540e\uff0c\u540d\u79f0\u548c\u7248\u672c\u53ef\u4ee5\u901a\u8fc7 <code class=\"function\">pg_get_loaded_modules()</code> \u51fd\u6570\u67e5\u770b\u3002\u7248\u672c\u5b57\u7b26\u4e32\u7684\u5177\u4f53\u542b\u4e49\u4e0d\u53d7 <span class=\"productname\">PostgreSQL</span> \u9650\u5236\uff0c\u4f46\u5efa\u8bae\u91c7\u7528\u8bed\u4e49\u5316\u7248\u672c\u89c4\u5219\u3002</p>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u5305\u542b\u4e00\u4e2a\u521d\u59cb\u5316\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code>\u7684\u51fd\u6570\uff0c\u90a3\u4e2a\u51fd\u6570\u5c06\u5728\u52a0\u8f7d\u6587\u4ef6\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u4efb\u4f55\u53c2\u6570\uff0c\u5e94\u8be5\u8fd4\u56devoid\u3002\u76ee\u524d\u6ca1\u6709\u529e\u6cd5\u5378\u8f7d\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-BASETYPE\">36.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u5c06\u5b83\u4eec\u4f20\u5165\u51fd\u6570\u548c\u4ece\u51fd\u6570\u4f20\u51fa\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/18/xaggr.html\" title=\"36.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a036.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td lang=\"zh\">\u6587\u672c</td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-V1-CALL-CONV\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-V1-CALL-CONV\">36.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u8981\u8c03\u7528\u53e6\u4e00\u4e2a\u7248\u672c-1 \u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">DirectFunctionCall<em class=\"replaceable\"><code>n</code></em>(func, arg1, ..., argn)</code>\u3002\u8fd9\u5728\u4f60\u60f3\u8c03\u7528\u6807\u51c6\u5185\u90e8\u5e93\u4e2d\u5b9a\u4e49\u7684\u51fd\u6570\u65f6\u5c24\u5176\u6709\u7528\uff0c\u56e0\u4e3a\u5b83\u63d0\u4f9b\u4e86\u4e0e\u5176 SQL \u7b7e\u540d\u76f8\u4f3c\u7684\u63a5\u53e3\u3002</p>\n<p lang=\"zh\">\u8fd9\u4e9b\u4fbf\u5229\u51fd\u6570\u4ee5\u53ca\u7c7b\u4f3c\u51fd\u6570\u90fd\u53ef\u4ee5\u5728 <code class=\"filename\">fmgr.h</code> \u4e2d\u627e\u5230\u3002<code class=\"function\">DirectFunctionCall<em class=\"replaceable\"><code>n</code></em></code> \u7cfb\u5217\u628a C \u51fd\u6570\u540d\u4f5c\u4e3a\u5176\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\u53e6\u6709 <code class=\"function\">OidFunctionCall<em class=\"replaceable\"><code>n</code></em></code> \u7b49\u4e00\u4e9b\u53d8\u4f53\uff0c\u5b83\u4eec\u63a5\u6536\u76ee\u6807\u51fd\u6570\u7684 OID\u3002\u6240\u6709\u8fd9\u4e9b\u51fd\u6570\u90fd\u8981\u6c42\u4ee5 <code class=\"type\">Datum</code> \u5f62\u5f0f\u63d0\u4f9b\u51fd\u6570\u53c2\u6570\uff0c\u8fd4\u56de\u503c\u4e5f\u540c\u6837\u662f <code class=\"type\">Datum</code>\u3002\u6ce8\u610f\uff0c\u4f7f\u7528\u8fd9\u4e9b\u4fbf\u5229\u51fd\u6570\u65f6\uff0c\u53c2\u6570\u548c\u7ed3\u679c\u90fd\u4e0d\u80fd\u4e3a NULL\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u8981\u5728 C \u4e2d\u8c03\u7528 <code class=\"function\">starts_with(text, text)</code>\uff0c\u4f60\u53ef\u4ee5\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\u67e5\u5230\u5b83\u7684 C \u5b9e\u73b0\u662f <code class=\"function\">Datum text_starts_with(PG_FUNCTION_ARGS)</code> \u51fd\u6570\u3002\u901a\u5e38\u4f60\u4f1a\u7528 <code class=\"literal\">DirectFunctionCall2(text_starts_with, ...)</code> \u6765\u8c03\u7528\u5b83\u3002\u4e0d\u8fc7\uff0c<code class=\"function\">starts_with(text, text)</code> \u9700\u8981\u6392\u5e8f\u89c4\u5219\u4fe1\u606f\uff0c\u56e0\u6b64\u5982\u679c\u8fd9\u6837\u8c03\u7528\uff0c\u4f1a\u56e0<span class=\"quote\">\u201c<span class=\"quote\">\u65e0\u6cd5\u786e\u5b9a\u5b57\u7b26\u4e32\u6bd4\u8f83\u8be5\u4f7f\u7528\u54ea\u4e00\u79cd\u6392\u5e8f\u89c4\u5219</span>\u201d</span>\u800c\u5931\u8d25\u3002\u4f60\u5fc5\u987b\u6539\u7528 <code class=\"literal\">DirectFunctionCall2Coll(text_starts_with, ...)</code>\uff0c\u5e76\u63d0\u4f9b\u6240\u9700\u7684\u6392\u5e8f\u89c4\u5219\uff0c\u901a\u5e38\u5c31\u662f\u4ece <code class=\"function\">PG_GET_COLLATION()</code> \u4f20\u9012\u8fdb\u6765\uff0c\u5982\u4e0b\u9762\u7684\u793a\u4f8b\u6240\u793a\u3002</p>\n<p lang=\"zh\"><code class=\"filename\">fmgr.h</code> \u8fd8\u63d0\u4f9b\u4e86\u4fbf\u4e8e\u5728 C \u7c7b\u578b\u548c <code class=\"type\">Datum</code> \u4e4b\u95f4\u8f6c\u6362\u7684\u5b8f\u3002\u4f8b\u5982\uff0c\u8981\u628a <code class=\"type\">Datum</code> \u8f6c\u6210 <code class=\"type\">text*</code>\uff0c\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">DatumGetTextPP(X)</code>\u3002\u867d\u7136\u67d0\u4e9b\u7c7b\u578b\u4e3a\u53cd\u5411\u8f6c\u6362\u63d0\u4f9b\u4e86\u540d\u4e3a <code class=\"function\">TypeGetDatum(X)</code> \u4e4b\u7c7b\u7684\u5b8f\uff0c\u4f46 <code class=\"type\">text*</code> \u6ca1\u6709\uff1b\u5bf9\u5b83\u800c\u8a00\uff0c\u76f4\u63a5\u4f7f\u7528\u901a\u7528\u5b8f <code class=\"function\">PointerGetDatum(X)</code> \u5373\u53ef\u3002\u5982\u679c\u4f60\u7684\u6269\u5c55\u5b9a\u4e49\u4e86\u989d\u5916\u7684\u7c7b\u578b\uff0c\u901a\u5e38\u4e5f\u5f88\u65b9\u4fbf\u4e3a\u8fd9\u4e9b\u7c7b\u578b\u5b9a\u4e49\u7c7b\u4f3c\u7684\u5b8f\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n#include \"varatt.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy(VARDATA(new_t),          /* destination */\n           VARDATA_ANY(t),          /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n/* A wrapper around starts_with(text, text) */\n\nPG_FUNCTION_INFO_V1(t_starts_with);\n\nDatum\nt_starts_with(PG_FUNCTION_ARGS)\n{\n    text       *t1 = PG_GETARG_TEXT_PP(0);\n    text       *t2 = PG_GETARG_TEXT_PP(1);\n    Oid         collid = PG_GET_COLLATION();\n    bool        result;\n\n    result = DatumGetBool(DirectFunctionCall2Coll(text_starts_with,\n                                                  collid,\n                                                  PointerGetDatum(t1),\n                                                  PointerGetDatum(t2)));\n    PG_RETURN_BOOL(result);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION t_starts_with(text, text) RETURNS boolean\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 't_starts_with'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"36.10.9.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a036.10.9\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/18/triggers.html\" title=\"\u7b2c\u00a037\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a037\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/18/plhandler.html\" title=\"\u7b2c\u00a057\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a057\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-CODE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-CODE\">36.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#DFUNC\">36.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 13.0 \u8d77\u9002\u7528\uff1b\u66f4\u65e9\u7248\u672c\u4f7f\u7528\u7684\u662f <code class=\"filename\">gcc</code> \u7f16\u8bd1\u5668\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-API-ABI-STABILITY-GUIDANCE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-API-ABI-STABILITY-GUIDANCE\">36.10.6. \u670d\u52a1\u5668 API \u548c ABI \u7a33\u5b9a\u6027\u6307\u5357</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u672c\u8282\u5411\u6269\u5c55\u548c\u5176\u4ed6\u670d\u52a1\u5668\u63d2\u4ef6\u7684\u4f5c\u8005\u63d0\u4f9b\u6709\u5173 <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668 API \u4e0e ABI \u7a33\u5b9a\u6027\u7684\u6307\u5bfc\u3002</p>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-GENERAL\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.1.\u00a0\u6982\u8ff0 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">PostgreSQL \u670d\u52a1\u5668\u4e3a\u63d2\u4ef6\u63d0\u4f9b\u4e86\u591a\u4e2a\u8fb9\u754c\u6e05\u6670\u7684 API\uff0c\u4f8b\u5982\u672c\u7ae0\u4ecb\u7ecd\u7684\u51fd\u6570\u7ba1\u7406\u5668 fmgr\u3001SPI\uff08\u7b2c 45 \u7ae0\uff09\u4ee5\u53ca\u4e13\u4e3a\u6269\u5c55\u8bbe\u8ba1\u7684\u5404\u79cd\u94a9\u5b50\u3002\u8fd9\u4e9b\u63a5\u53e3\u7ecf\u8fc7\u8c28\u614e\u7ef4\u62a4\uff0c\u4ee5\u4fdd\u6301\u957f\u671f\u7a33\u5b9a\u6027\u548c\u517c\u5bb9\u6027\u3002\u4e0d\u8fc7\uff0c\u670d\u52a1\u5668\u4e2d\u5168\u90e8\u5168\u5c40\u51fd\u6570\u548c\u53d8\u91cf\u5b9e\u9645\u4e0a\u90fd\u6784\u6210\u4e86\u53ef\u516c\u5f00\u4f7f\u7528\u7684 API\uff0c\u5176\u4e2d\u5927\u90e8\u5206\u5728\u8bbe\u8ba1\u65f6\u5e76\u672a\u8003\u8651\u53ef\u6269\u5c55\u6027\u548c\u957f\u671f\u7a33\u5b9a\u6027\u3002</p>\n<p lang=\"zh\">\u56e0\u6b64\uff0c\u867d\u7136\u4f7f\u7528\u8fd9\u4e9b\u63a5\u53e3\u662f\u5b8c\u5168\u5141\u8bb8\u7684\uff0c\u4f46\u8d8a\u662f\u504f\u79bb\u90a3\u4e9b\u4e45\u7ecf\u5b9e\u8df5\u8003\u9a8c\u7684\u8def\u5f84\uff0c\u5c06\u6765\u9047\u5230 API \u6216 ABI \u517c\u5bb9\u6027\u95ee\u9898\u7684\u53ef\u80fd\u6027\u5c31\u8d8a\u5927\u3002\u9f13\u52b1\u6269\u5c55\u4f5c\u8005\u53cd\u9988\u81ea\u5df1\u7684\u9700\u6c42\uff0c\u4ee5\u4fbf\u968f\u7740\u65f6\u95f4\u63a8\u79fb\u548c\u65b0\u7528\u6cd5\u7684\u51fa\u73b0\uff0c\u67d0\u4e9b\u63a5\u53e3\u80fd\u591f\u88ab\u89c6\u4e3a\u66f4\u7a33\u5b9a\uff0c\u6216\u8005\u53ef\u4ee5\u52a0\u5165\u65b0\u7684\u3001\u8bbe\u8ba1\u66f4\u5b8c\u5584\u7684\u63a5\u53e3\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-API-COMPATIBILITY\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.2.\u00a0API \u517c\u5bb9\u6027 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">API\uff0c\u5373\u5e94\u7528\u7a0b\u5e8f\u7f16\u7a0b\u63a5\u53e3\uff0c\u662f\u7f16\u8bd1\u65f6\u4f7f\u7528\u7684\u63a5\u53e3\u3002</p>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-API-MAJOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.2.1.\u00a0Major Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728 <span class=\"productname\">PostgreSQL</span> \u4e0d\u540c\u4e3b\u7248\u672c\u4e4b\u95f4\uff0c<span class=\"emphasis\"><em>\u4e0d\u627f\u8bfa</em></span> API \u517c\u5bb9\u6027\u3002\u56e0\u6b64\uff0c\u6269\u5c55\u4ee3\u7801\u53ef\u80fd\u9700\u8981\u4fee\u6539\u6e90\u4ee3\u7801\u624d\u80fd\u540c\u65f6\u652f\u6301\u591a\u4e2a\u4e3b\u7248\u672c\u3002\u8fd9\u7c7b\u5dee\u5f02\u901a\u5e38\u53ef\u4ee5\u901a\u8fc7\u9884\u5904\u7406\u5668\u6761\u4ef6\uff08\u4f8b\u5982 <code class=\"literal\">#if PG_VERSION_NUM &gt;= 160000</code>\uff09\u6765\u7ba1\u7406\u3002\u90a3\u4e9b\u4f7f\u7528\u4e86\u8fb9\u754c\u6e05\u6670\u63a5\u53e3\u4e4b\u5916\u80fd\u529b\u7684\u590d\u6742\u6269\u5c55\uff0c\u901a\u5e38\u6bcf\u4e2a\u670d\u52a1\u5668\u4e3b\u7248\u672c\u90fd\u9700\u8981\u505a\u5c11\u91cf\u8fd9\u7c7b\u4fee\u6539\u3002</p>\n</div>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-API-MNINOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.2.2.\u00a0Minor Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u529b\u907f\u514d\u5728\u5c0f\u7248\u672c\u53d1\u5e03\u4e2d\u7834\u574f\u670d\u52a1\u5668 API\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u80fd\u9488\u5bf9\u67d0\u4e2a\u5c0f\u7248\u672c\u7f16\u8bd1\u5e76\u6b63\u5e38\u5de5\u4f5c\u7684\u6269\u5c55\u4ee3\u7801\uff0c\u4e5f\u5e94\u5f53\u80fd\u591f\u9488\u5bf9\u540c\u4e00\u4e3b\u7248\u672c\u7684\u5176\u4ed6\u4efb\u610f\u5c0f\u7248\u672c\uff08\u65e0\u8bba\u8fc7\u53bb\u8fd8\u662f\u5c06\u6765\uff09\u7f16\u8bd1\u5e76\u6b63\u5e38\u5de5\u4f5c\u3002</p>\n<p lang=\"zh\">\u5982\u679c<span class=\"emphasis\"><em>\u786e\u5b9e</em></span>\u9700\u8981\u505a\u51fa\u53d8\u66f4\uff0c\u4e5f\u4f1a\u5728\u8003\u8651\u6269\u5c55\u9700\u6c42\u7684\u524d\u63d0\u4e0b\u8c28\u614e\u7ba1\u7406\u3002\u8fd9\u7c7b\u53d8\u66f4\u4f1a\u5728\u53d1\u5e03\u8bf4\u660e\uff08<a class=\"xref\" href=\"/docs/18/release.html\" title=\"\u9644\u5f55\u00a0E.\u00a0\u53d1\u5e03\u8bf4\u660e\">\u9644\u5f55\u00a0E</a>\uff09\u4e2d\u8fdb\u884c\u8bf4\u660e\u3002</p>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-ABI-COMPATIBILITY\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.3.\u00a0ABI \u517c\u5bb9\u6027 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">ABI\uff0c\u5373\u5e94\u7528\u7a0b\u5e8f\u4e8c\u8fdb\u5236\u63a5\u53e3\uff0c\u662f\u8fd0\u884c\u65f6\u4f7f\u7528\u7684\u63a5\u53e3\u3002</p>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-ABI-MAJOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.3.1.\u00a0Major Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u4e0d\u540c\u4e3b\u7248\u672c\u7684\u670d\u52a1\u5668\u5728 ABI \u4e0a\u662f\u6709\u610f\u4e0d\u517c\u5bb9\u7684\u3002\u56e0\u6b64\uff0c\u4f7f\u7528\u670d\u52a1\u5668 API \u7684\u6269\u5c55\u5fc5\u987b\u9488\u5bf9\u6bcf\u4e00\u4e2a\u4e3b\u7248\u672c\u91cd\u65b0\u7f16\u8bd1\u3002\u5305\u542b <code class=\"literal\">PG_MODULE_MAGIC</code>\uff08\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\uff09\u53ef\u4ee5\u786e\u4fdd\u9488\u5bf9\u67d0\u4e2a\u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u4ee3\u7801\u4f1a\u88ab\u5176\u4ed6\u4e3b\u7248\u672c\u62d2\u7edd\u3002</p>\n</div>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-ABI-MNINOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.3.2.\u00a0Minor Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u529b\u907f\u514d\u5728\u5c0f\u7248\u672c\u53d1\u5e03\u4e2d\u7834\u574f\u670d\u52a1\u5668 ABI\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u9488\u5bf9\u4efb\u610f\u4e00\u4e2a\u5c0f\u7248\u672c\u7f16\u8bd1\u7684\u6269\u5c55\uff0c\u5e94\u5f53\u80fd\u4e0e\u540c\u4e00\u4e3b\u7248\u672c\u8fc7\u53bb\u6216\u5c06\u6765\u7684\u5176\u4ed6\u4efb\u610f\u5c0f\u7248\u672c\u4e00\u8d77\u5de5\u4f5c\u3002</p>\n<p lang=\"zh\">\u5982\u679c<span class=\"emphasis\"><em>\u786e\u5b9e</em></span>\u9700\u8981\u53d8\u66f4\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u91cf\u9009\u62e9\u4fb5\u5165\u6027\u6700\u5c0f\u7684\u65b9\u5f0f\uff0c\u4f8b\u5982\u628a\u65b0\u5b57\u6bb5\u585e\u8fdb\u586b\u5145\u7a7a\u95f4\uff0c\u6216\u8005\u9644\u52a0\u5230\u7ed3\u6784\u4f53\u672b\u5c3e\u3002\u8fd9\u7c7b\u4fee\u6539\u901a\u5e38\u4e0d\u5e94\u5f71\u54cd\u6269\u5c55\uff0c\u9664\u975e\u6269\u5c55\u4f7f\u7528\u4e86\u975e\u5e38\u4e0d\u5bfb\u5e38\u7684\u4ee3\u7801\u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u7136\u800c\uff0c\u5728\u6781\u5c11\u6570\u60c5\u51b5\u4e0b\uff0c\u5373\u4f7f\u662f\u8fd9\u79cd\u975e\u4fb5\u5165\u5f0f\u53d8\u66f4\u4e5f\u53ef\u80fd\u4e0d\u73b0\u5b9e\u751a\u81f3\u4e0d\u53ef\u80fd\u505a\u5230\u3002\u53d1\u751f\u8fd9\u79cd\u60c5\u51b5\u65f6\uff0c\u4e5f\u4f1a\u5728\u8003\u8651\u6269\u5c55\u9700\u6c42\u7684\u524d\u63d0\u4e0b\u8c28\u614e\u7ba1\u7406\u8be5\u53d8\u66f4\u3002\u8fd9\u7c7b\u53d8\u66f4\u540c\u6837\u4f1a\u8bb0\u5f55\u5728\u53d1\u5e03\u8bf4\u660e\uff08<a class=\"xref\" href=\"/docs/18/release.html\" title=\"\u9644\u5f55\u00a0E.\u00a0\u53d1\u5e03\u8bf4\u660e\">\u9644\u5f55\u00a0E</a>\uff09\u4e2d\u3002</p>\n<p lang=\"zh\">\u4f46\u8bf7\u6ce8\u610f\uff0c\u670d\u52a1\u5668\u4e2d\u6709\u5f88\u591a\u90e8\u5206\u5e76\u4e0d\u662f\u4f5c\u4e3a\u53ef\u516c\u5f00\u4f7f\u7528\u7684 API \u6765\u8bbe\u8ba1\u548c\u7ef4\u62a4\u7684\uff08\u800c\u4e14\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u5176\u771f\u5b9e\u8fb9\u754c\u4e5f\u5e76\u4e0d\u6e05\u6670\uff09\u3002\u5982\u679c\u51fa\u73b0\u7d27\u6025\u9700\u6c42\uff0c\u5bf9\u8fd9\u4e9b\u90e8\u5206\u8fdb\u884c\u4fee\u6539\u65f6\uff0c\u81ea\u7136\u4f1a\u6bd4\u4fee\u6539\u90a3\u4e9b\u8fb9\u754c\u6e05\u695a\u4e14\u5e7f\u6cdb\u4f7f\u7528\u7684\u63a5\u53e3\u65f6\u66f4\u5c11\u8003\u8651\u6269\u5c55\u4ee3\u7801\u7684\u517c\u5bb9\u6027\u3002</p>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5728\u7f3a\u4e4f\u81ea\u52a8\u5316\u68c0\u6d4b\u8fd9\u7c7b\u53d8\u5316\u7684\u673a\u5236\u65f6\uff0c\u8fd9\u5e76\u4e0d\u80fd\u6784\u6210\u4e25\u683c\u4fdd\u8bc1\uff1b\u4e0d\u8fc7\u4ece\u5386\u53f2\u4e0a\u770b\uff0c\u8fd9\u79cd\u7834\u574f\u6027\u53d8\u5316\u6781\u4e3a\u7f55\u89c1\u3002</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-COMPOSITE-TYPE-ARGS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-COMPOSITE-TYPE-ARGS\">36.10.7. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u51fd\u6570\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURNING-ROWS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-RETURNING-ROWS\">36.10.8. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-RETURN-SET\">36.10.9. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_INT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-POLYMORPHIC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-POLYMORPHIC\">36.10.10. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de<a class=\"xref\" href=\"/docs/18/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"36.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a036.2.5\u00a0\u8282</a>\u4e2d\u63cf\u8ff0\u7684\u591a\u6001\u7c7b\u578b\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-SHARED-ADDIN\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-SHARED-ADDIN\">36.10.11. \u5171\u4eab\u5185\u5b58</a></span></h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u3002\u4e3a\u6b64\uff0c\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\uff0c\u5e76\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\u3002\u6b64\u94a9\u5b50\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559\u5171\u4eab\u5185\u5b58\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(Size size)\n</pre>\n<p lang=\"zh\">\u6765\u9884\u7559\u5171\u4eab\u5185\u5b58\u3002\u6bcf\u4e2a\u540e\u7aef\u90fd\u5e94\u5f53\u901a\u8fc7\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">void *ShmemInitStruct(const char *name, Size size, bool *foundPtr)\n</pre>\n<p lang=\"zh\">\u6765\u83b7\u53d6\u6307\u5411\u8fd9\u5757\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u6307\u9488\u3002\u5982\u679c\u8be5\u51fd\u6570\u628a <code class=\"literal\">foundPtr</code> \u8bbe\u4e3a <code class=\"literal\">false</code>\uff0c\u8c03\u7528\u8005\u5c31\u5e94\u521d\u59cb\u5316\u8fd9\u5757\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u5185\u5bb9\uff1b\u5982\u679c <code class=\"literal\">foundPtr</code> \u4e3a <code class=\"literal\">true</code>\uff0c\u8bf4\u660e\u8be5\u5171\u4eab\u5185\u5b58\u5df2\u7ecf\u7531\u5176\u4ed6\u540e\u7aef\u521d\u59cb\u5316\u8fc7\uff0c\u8c03\u7528\u8005\u65e0\u9700\u518d\u505a\u521d\u59cb\u5316\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u4e89\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u521d\u59cb\u5316\u5176\u5171\u4eab\u5185\u5b58\u5206\u914d\u65f6\u90fd\u5e94\u4f7f\u7528 LWLock <code class=\"function\">AddinShmemInitLock</code>\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\nbool        found;\n\nLWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\nptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\nif (!found)\n{\n    ... initialize contents of shared memory ...\n    ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n}\nLWLockRelease(AddinShmemInitLock);\n</pre>\n<p lang=\"zh\"><code class=\"literal\">shmem_startup_hook</code> \u4e3a\u521d\u59cb\u5316\u4ee3\u7801\u63d0\u4f9b\u4e86\u4e00\u4e2a\u65b9\u4fbf\u7684\u4f4d\u7f6e\uff0c\u4f46\u5e76\u4e0d\u5f3a\u5236\u8981\u6c42\u6240\u6709\u8fd9\u7c7b\u4ee3\u7801\u90fd\u653e\u5728\u8fd9\u4e2a\u94a9\u5b50\u4e2d\u3002\u5728 Windows \u4e0a\uff08\u4ee5\u53ca\u4efb\u4f55\u5b9a\u4e49\u4e86 <code class=\"literal\">EXEC_BACKEND</code> \u7684\u5e73\u53f0\u4e0a\uff09\uff0c\u6bcf\u4e2a\u540e\u7aef\u90fd\u4f1a\u5728\u9644\u52a0\u5230\u5171\u4eab\u5185\u5b58\u540e\u4e0d\u4e45\u6267\u884c\u5df2\u6ce8\u518c\u7684 <code class=\"literal\">shmem_startup_hook</code>\uff0c\u56e0\u6b64\u63d2\u4ef6\u5728\u8be5\u94a9\u5b50\u4e2d\u4ecd\u5e94\u50cf\u4e0a\u4f8b\u90a3\u6837\u83b7\u53d6 <code class=\"function\">AddinShmemInitLock</code>\u3002\u5728\u5176\u4ed6\u5e73\u53f0\u4e0a\uff0c\u53ea\u6709 postmaster \u8fdb\u7a0b\u4f1a\u6267\u884c <code class=\"literal\">shmem_startup_hook</code>\uff0c\u6bcf\u4e2a\u540e\u7aef\u4f1a\u81ea\u52a8\u7ee7\u627f\u8fd9\u4e9b\u5171\u4eab\u5185\u5b58\u6307\u9488\u3002</p>\n<p lang=\"zh\"><code class=\"literal\">shmem_request_hook</code> \u4e0e <code class=\"literal\">shmem_startup_hook</code> \u7684\u4e00\u4e2a\u5b8c\u6574\u793a\u4f8b\u53ef\u89c1\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_stat_statements/pg_stat_statements.c</code>\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.2.\u00a0\u542f\u52a8\u540e\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u4e4b\u540e\uff0c\u5e76\u4e14\u65e0\u9700\u501f\u52a9 <code class=\"literal\">shmem_request_hook</code> \u6765\u5b8c\u6210\u3002\u4e3a\u6b64\uff0c\u6bcf\u4e2a\u9700\u8981\u4f7f\u7528\u8be5\u5171\u4eab\u5185\u5b58\u7684\u540e\u7aef\u90fd\u5e94\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u83b7\u53d6\u4e00\u4e2a\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">void *GetNamedDSMSegment(const char *name, size_t size,\n                         void (*init_callback) (void *ptr),\n                         bool *found)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u7ed9\u5b9a\u540d\u79f0\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u5c1a\u4e0d\u5b58\u5728\uff0c\u8be5\u51fd\u6570\u4f1a\u5206\u914d\u8be5\u6bb5\uff0c\u5e76\u4f7f\u7528\u63d0\u4f9b\u7684 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u5bf9\u5176\u8fdb\u884c\u521d\u59cb\u5316\u3002\u5982\u679c\u8be5\u6bb5\u5df2\u7ecf\u7531\u53e6\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8fc7\uff0c\u8be5\u51fd\u6570\u5c31\u53ea\u4f1a\u628a\u73b0\u6709\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u9644\u52a0\u5230\u5f53\u524d\u540e\u7aef\u3002</p>\n<p lang=\"zh\">\u4e0e\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559\u7684\u5171\u4eab\u5185\u5b58\u4e0d\u540c\uff0c\u4f7f\u7528 GetNamedDSMSegment \u9884\u7559\u5171\u4eab\u5185\u5b58\u65f6\uff0c\u65e0\u9700\u83b7\u53d6 AddinShmemInitLock\uff0c\u4e5f\u65e0\u9700\u91c7\u53d6\u5176\u4ed6\u63aa\u65bd\u907f\u514d\u7ade\u6001\u6761\u4ef6\u3002\u6b64\u51fd\u6570\u4fdd\u8bc1\u4ec5\u7531\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8be5\u6bb5\uff0c\u5176\u4ed6\u6240\u6709\u540e\u7aef\u83b7\u5f97\u7684\u90fd\u662f\u6307\u5411\u5df2\u5b8c\u5168\u5206\u914d\u5e76\u521d\u59cb\u5316\u7684\u6bb5\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\"><code class=\"function\">GetNamedDSMSegment</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/test_dsm_registry/test_dsm_registry.c</code>\uff0c\u4f4d\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-LWLOCKS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\">36.10.12. \u8f7b\u91cf\u7ea7\u9501\uff08LWLocks\uff09</h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.12.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLocks\u3002\u4e0e\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u4e00\u6837\uff0c\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\uff0c\u5e76\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\u3002\u6b64\u94a9\u5b50\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8fd9\u786e\u4fdd\u5b58\u5728\u4e00\u4e2a\u540d\u4e3a tranche_name\u3001\u5305\u542b num_lwlocks \u4e2a LWLocks \u7684\u6570\u7ec4\u3002\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u53d6\u5f97\u8be5\u6570\u7ec4\u7684\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">LWLockPadded *GetNamedLWLockTranche(const char *tranche_name)\n</pre>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.12.2.\u00a0\u542f\u52a8\u540e\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u83b7\u53d6 LWLocks \u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u540e\u8fdb\u884c\uff0c\u4e5f\u65e0\u9700\u501f\u52a9 <code class=\"literal\">shmem_request_hook</code>\u3002\u4e3a\u6b64\uff0c\u9996\u5148\u901a\u8fc7\u8c03\u7528\u4e0b\u9762\u7684\u51fd\u6570\u5206\u914d\u4e00\u4e2a <code class=\"literal\">tranche_id</code>\uff1a</p>\n<pre class=\"programlisting\">int LWLockNewTrancheId(void)\n</pre>\n<p lang=\"zh\">\u63a5\u4e0b\u6765\uff0c\u521d\u59cb\u5316\u6bcf\u4e2a LWLock\uff0c\u5e76\u628a\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\uff1a</p>\n<pre class=\"programlisting\">void LWLockInitialize(LWLock *lock, int tranche_id)\n</pre>\n<p lang=\"zh\">\u4e0e\u5171\u4eab\u5185\u5b58\u7c7b\u4f3c\uff0c\u6bcf\u4e2a\u540e\u7aef\u90fd\u5e94\u786e\u4fdd\u53ea\u6709\u4e00\u4e2a\u8fdb\u7a0b\u4f1a\u5206\u914d\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u5e76\u521d\u59cb\u5316\u6bcf\u4e00\u4e2a\u65b0\u7684 LWLock\u3002\u4e00\u79cd\u505a\u6cd5\u662f\u4ec5\u5728\u6301\u6709 <code class=\"function\">AddinShmemInitLock</code> \u72ec\u5360\u9501\u7684\u5171\u4eab\u5185\u5b58\u521d\u59cb\u5316\u4ee3\u7801\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u3002\u5982\u679c\u4f7f\u7528 <code class=\"function\">GetNamedDSMSegment</code>\uff0c\u90a3\u4e48\u5728 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u5c31\u8db3\u4ee5\u907f\u514d\u7ade\u4e89\u6761\u4ef6\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6bcf\u4e2a\u4f7f\u7528\u8be5 <code class=\"literal\">tranche_id</code> \u7684\u540e\u7aef\u90fd\u5e94\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u628a\u5b83\u4e0e\u4e00\u4e2a <code class=\"literal\">tranche_name</code> \u5173\u8054\u8d77\u6765\uff1a</p>\n<pre class=\"programlisting\">void LWLockRegisterTranche(int tranche_id, const char *tranche_name)\n</pre>\n<p lang=\"zh\"><code class=\"function\">LWLockNewTrancheId</code>\u3001<code class=\"function\">LWLockInitialize</code> \u548c <code class=\"function\">LWLockRegisterTranche</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_prewarm/autoprewarm.c</code>\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-WAIT-EVENTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-ADDIN-WAIT-EVENTS\">36.10.13. \u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u5728\u7b49\u5f85\u4e8b\u4ef6\u7c7b\u578b <code class=\"literal\">Extension</code> \u4e0b\u5b9a\u4e49\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\uff1a</p>\n<pre class=\"programlisting\">uint32 WaitEventExtensionNew(const char *wait_event_name)\n</pre>\n<p lang=\"zh\">\u8be5\u7b49\u5f85\u4e8b\u4ef6\u4f1a\u5173\u8054\u5230\u4e00\u4e2a\u9762\u5411\u7528\u6237\u7684\u81ea\u5b9a\u4e49\u5b57\u7b26\u4e32\u3002\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/worker_spi</code>\uff0c\u4f4d\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n<p lang=\"zh\">\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\u53ef\u4ee5\u5728 <a class=\"link\" href=\"/docs/18/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW\" title=\"27.2.3.\u00a0pg_stat_activity\"><code class=\"structname\">pg_stat_activity</code></a> \u4e2d\u67e5\u770b\uff1a</p>\n<pre class=\"screen\">=# SELECT wait_event_type, wait_event FROM pg_stat_activity\n     WHERE backend_type ~ 'worker_spi';\n wait_event_type |  wait_event\n-----------------+---------------\n Extension       | WorkerSpiMain\n(1 row)\n</pre>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-INJECTION-POINTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-ADDIN-INJECTION-POINTS\">36.10.14. \u6ce8\u5165\u70b9</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7ed9\u5b9a\u540d\u79f0 <code class=\"literal\">name</code> \u7684\u6ce8\u5165\u70b9\u53ef\u901a\u8fc7\u4ee5\u4e0b\u5b8f\u58f0\u660e\uff1a</p>\n<pre class=\"programlisting\">INJECTION_POINT(name, arg);\n</pre>\n<p lang=\"zh\">\u670d\u52a1\u5668\u4ee3\u7801\u4e2d\u5df2\u7ecf\u5728\u82e5\u5e72\u5173\u952e\u4f4d\u7f6e\u58f0\u660e\u4e86\u6ce8\u5165\u70b9\u3002\u65b0\u589e\u6ce8\u5165\u70b9\u540e\uff0c\u9700\u8981\u91cd\u65b0\u7f16\u8bd1\u4ee3\u7801\uff0c\u624d\u80fd\u8ba9\u8be5\u6ce8\u5165\u70b9\u51fa\u73b0\u5728\u4e8c\u8fdb\u5236\u6587\u4ef6\u4e2d\u3002\u7528 C \u8bed\u8a00\u7f16\u5199\u7684\u63d2\u4ef6\u4e5f\u53ef\u4ee5\u4f7f\u7528\u540c\u4e00\u4e2a\u5b8f\u5728\u81ea\u5df1\u7684\u4ee3\u7801\u4e2d\u58f0\u660e\u6ce8\u5165\u70b9\u3002\u6ce8\u5165\u70b9\u540d\u79f0\u5e94\u4f7f\u7528\u5c0f\u5199\u5b57\u6bcd\uff0c\u5e76\u7528\u8fde\u5b57\u7b26\u5206\u9694\u5404\u4e2a\u672f\u8bed\u3002<code class=\"literal\">arg</code> \u662f\u8fd0\u884c\u65f6\u4f20\u7ed9\u56de\u8c03\u7684\u53ef\u9009\u53c2\u6570\u503c\u3002</p>\n<p lang=\"zh\">\u6267\u884c\u6ce8\u5165\u70b9\u53ef\u80fd\u9700\u8981\u5206\u914d\u5c11\u91cf\u5185\u5b58\uff0c\u800c\u8fd9\u53ef\u80fd\u5931\u8d25\u3002\u5982\u679c\u4f60\u9700\u8981\u5728\u4e00\u4e2a\u4e0d\u5141\u8bb8\u52a8\u6001\u5206\u914d\u7684\u4e34\u754c\u533a\u4e2d\u4f7f\u7528\u6ce8\u5165\u70b9\uff0c\u53ef\u4ee5\u91c7\u7528\u4ee5\u4e0b\u4e24\u6b65\u6cd5\uff1a</p>\n<pre class=\"programlisting\">INJECTION_POINT_LOAD(name);\nINJECTION_POINT_CACHED(name, arg);\n</pre>\n<p lang=\"zh\">\u5728\u8fdb\u5165\u4e34\u754c\u533a\u4e4b\u524d\uff0c\u8c03\u7528 <code class=\"function\">INJECTION_POINT_LOAD</code>\u3002\u5b83\u4f1a\u68c0\u67e5\u5171\u4eab\u5185\u5b58\u72b6\u6001\uff0c\u5e76\u5728\u8be5\u6ce8\u5165\u70b9\u5904\u4e8e\u6fc0\u6d3b\u72b6\u6001\u65f6\u628a\u56de\u8c03\u52a0\u8f7d\u5230\u540e\u7aef\u79c1\u6709\u5185\u5b58\u4e2d\u3002\u5728\u4e34\u754c\u533a\u5185\u90e8\uff0c\u518d\u7528 <code class=\"function\">INJECTION_POINT_CACHED</code> \u6765\u6267\u884c\u56de\u8c03\u3002</p>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u4e3a\u4e00\u4e2a\u5df2\u7ecf\u58f0\u660e\u597d\u7684\u6ce8\u5165\u70b9\u9644\u52a0\u56de\u8c03\uff1a</p>\n<pre class=\"programlisting\">extern void InjectionPointAttach(const char *name,\n                                 const char *library,\n                                 const char *function,\n                                 const void *private_data,\n                                 int private_data_size);\n</pre>\n<p lang=\"zh\">name \u662f\u6ce8\u5165\u70b9\u7684\u540d\u79f0\uff1b\u6267\u884c\u5230\u8fbe\u6b64\u6ce8\u5165\u70b9\u65f6\uff0c\u5c06\u6267\u884c\u4ece library \u52a0\u8f7d\u7684\u51fd\u6570\u3002private_data \u662f\u4e00\u5757\u5927\u5c0f\u4e3a private_data_size \u7684\u79c1\u6709\u6570\u636e\u533a\u57df\uff0c\u5728\u6267\u884c\u56de\u8c03\u65f6\u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a <code class=\"literal\">InjectionPointCallback</code> \u7684\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">static void\ncustom_injection_callback(const char *name,\n                          const void *private_data,\n                          void *arg)\n{\n    uint32 wait_event_info = WaitEventInjectionPointNew(name);\n\n    pgstat_report_wait_start(wait_event_info);\n    elog(NOTICE, \"%s: executed custom callback\", name);\n    pgstat_report_wait_end();\n}\n</pre>\n<p lang=\"zh\">\u8fd9\u4e2a\u56de\u8c03\u4f1a\u4ee5 <code class=\"literal\">NOTICE</code> \u7ea7\u522b\u5411\u670d\u52a1\u5668\u9519\u8bef\u65e5\u5fd7\u5199\u5165\u4e00\u6761\u6d88\u606f\uff0c\u4f46\u56de\u8c03\u5b8c\u5168\u53ef\u4ee5\u5b9e\u73b0\u66f4\u590d\u6742\u7684\u903b\u8f91\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u5b9a\u4e49\u201c\u5230\u8fbe\u6ce8\u5165\u70b9\u65f6\u5e94\u6267\u884c\u4ec0\u4e48\u52a8\u4f5c\u201d\u7684\u65b9\u5f0f\uff0c\u662f\u628a\u6d4b\u8bd5\u4ee3\u7801\u76f4\u63a5\u5199\u5728\u5e38\u89c4\u6e90\u4ee3\u7801\u65c1\u8fb9\u3002\u5982\u679c\u8be5\u52a8\u4f5c\u4f9d\u8d56\u4e8e\u52a0\u8f7d\u6a21\u5757\u65e0\u6cd5\u8bbf\u95ee\u7684\u5c40\u90e8\u53d8\u91cf\uff0c\u8fd9\u4f1a\u5f88\u6709\u7528\u3002\u6b64\u65f6\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">IS_INJECTION_POINT_ATTACHED</code> \u5b8f\u6765\u68c0\u67e5\u67d0\u4e2a\u6ce8\u5165\u70b9\u662f\u5426\u5df2\u9644\u52a0\uff0c\u4f8b\u5982\uff1a</p>\n<pre class=\"programlisting\">#ifdef USE_INJECTION_POINTS\nif (IS_INJECTION_POINT_ATTACHED(\"before-foobar\"))\n{\n    /* change a local variable if injection point is attached */\n    local_var = 123;\n\n    /* also execute the callback */\n    INJECTION_POINT_CACHED(\"before-foobar\", NULL);\n}\n#endif\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\uff0c\u9644\u52a0\u5230\u6ce8\u5165\u70b9\u4e0a\u7684\u56de\u8c03\u4e0d\u4f1a\u7531 <code class=\"function\">IS_INJECTION_POINT_ATTACHED</code> \u5b8f\u6267\u884c\u3002\u5982\u679c\u4f60\u60f3\u6267\u884c\u8be5\u56de\u8c03\uff0c\u5c31\u5fc5\u987b\u50cf\u4e0a\u9762\u7684\u793a\u4f8b\u90a3\u6837\u53e6\u5916\u8c03\u7528 <code class=\"function\">INJECTION_POINT_CACHED</code>\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u89e3\u9664\u4e00\u4e2a\u6ce8\u5165\u70b9\uff1a</p>\n<pre class=\"programlisting\">extern bool InjectionPointDetach(const char *name);\n</pre>\n<p lang=\"zh\">\u6210\u529f\u65f6\u8fd4\u56de <code class=\"literal\">true</code>\uff0c\u5426\u5219\u8fd4\u56de <code class=\"literal\">false</code>\u3002</p>\n<p lang=\"zh\">\u4e00\u4e2a\u9644\u52a0\u5230\u6ce8\u5165\u70b9\u7684\u56de\u8c03\u4f1a\u5728\u6240\u6709\u540e\u7aef\u4e2d\u751f\u6548\uff0c\u5305\u62ec\u5728\u8c03\u7528 <code class=\"literal\">InjectionPointAttach</code> \u4e4b\u540e\u624d\u542f\u52a8\u7684\u540e\u7aef\u3002\u5b83\u4f1a\u4e00\u76f4\u4fdd\u6301\u9644\u52a0\u72b6\u6001\uff0c\u76f4\u5230\u670d\u52a1\u5668\u505c\u6b62\uff0c\u6216\u8005\u901a\u8fc7 <code class=\"literal\">InjectionPointDetach</code> \u5c06\u5176\u89e3\u9664\u3002</p>\n<p lang=\"zh\">\u76f8\u5173\u793a\u4f8b\u53ef\u89c1\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">src/test/modules/injection_points</code>\u3002</p>\n<p lang=\"zh\">\u8981\u542f\u7528\u6ce8\u5165\u70b9\uff0c\u4f7f\u7528 configure \u65f6\u9700\u6307\u5b9a --enable-injection-points\uff0c\u4f7f\u7528 Meson \u65f6\u9700\u6307\u5b9a -Dinjection_points=true\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-CUSTOM-CUMULATIVE-STATISTICS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-ADDIN-CUSTOM-CUMULATIVE-STATISTICS\">36.10.15. \u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528 C \u8bed\u8a00\u7f16\u5199\u7684\u63d2\u4ef6\u53ef\u4ee5\u4f7f\u7528\u5728<a class=\"link\" href=\"/docs/18/monitoring-stats.html#MONITORING-STATS-SETUP\" title=\"27.2.1.\u00a0\u7edf\u8ba1\u4fe1\u606f\u6536\u96c6\u914d\u7f6e\">\u7d2f\u8ba1\u7edf\u8ba1\u7cfb\u7edf</a>\u4e2d\u6ce8\u518c\u7684\u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u9996\u5148\uff0c\u5b9a\u4e49\u4e00\u4e2a <code class=\"literal\">PgStat_KindInfo</code>\uff0c\u5176\u4e2d\u5305\u542b\u4e0e\u6240\u6ce8\u518c\u81ea\u5b9a\u4e49\u7c7b\u578b\u76f8\u5173\u7684\u5168\u90e8\u4fe1\u606f\u3002\u4f8b\u5982\uff1a</p>\n<pre class=\"programlisting\">static const PgStat_KindInfo custom_stats = {\n    .name = \"custom_stats\",\n    .fixed_amount = false,\n    .shared_size = sizeof(PgStatShared_Custom),\n    .shared_data_off = offsetof(PgStatShared_Custom, stats),\n    .shared_data_len = sizeof(((PgStatShared_Custom *) 0)-&gt;stats),\n    .pending_size = sizeof(PgStat_StatCustomEntry),\n}\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff0c\u6bcf\u4e2a\u9700\u8981\u4f7f\u7528\u8fd9\u79cd\u81ea\u5b9a\u4e49\u7c7b\u578b\u7684\u540e\u7aef\uff0c\u90fd\u9700\u8981\u4f7f\u7528 <code class=\"literal\">pgstat_register_kind</code> \u6ce8\u518c\u5b83\uff0c\u5e76\u6307\u5b9a\u4e00\u4e2a\u7528\u4e8e\u5b58\u50a8\u8be5\u7c7b\u7edf\u8ba1\u6761\u76ee\u7684\u552f\u4e00 ID\uff1a</p>\n<pre class=\"programlisting\">extern PgStat_Kind pgstat_register_kind(PgStat_Kind kind,\n                                        const PgStat_KindInfo *kind_info);\n</pre>\n<p lang=\"zh\">\u5728\u5f00\u53d1\u65b0\u6269\u5c55\u65f6\uff0c\u5e94\u5c06 <code class=\"literal\">PGSTAT_KIND_EXPERIMENTAL</code> \u7528\u4f5c <em class=\"parameter\"><code>kind</code></em>\u3002\u5f53\u4f60\u51c6\u5907\u628a\u6269\u5c55\u53d1\u5e03\u7ed9\u7528\u6237\u65f6\uff0c\u8bf7\u5728 <a class=\"ulink\" href=\"https://wiki.postgresql.org/wiki/CustomCumulativeStats\" target=\"_top\">Custom Cumulative Statistics</a> \u9875\u9762\u4e0a\u9884\u7559\u4e00\u4e2a kind ID\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e <code class=\"literal\">PgStat_KindInfo</code> API \u7684\u7ec6\u8282\uff0c\u53ef\u89c1 <code class=\"filename\">src/include/utils/pgstat_internal.h</code>\u3002</p>\n<p lang=\"zh\">\u5df2\u6ce8\u518c\u7684\u7edf\u8ba1\u7c7b\u578b\u4f1a\u5173\u8054\u5230\u4e00\u4e2a\u540d\u79f0\u4ee5\u53ca\u4e00\u4e2a\u5728\u5171\u4eab\u5185\u5b58\u4e2d\u4f9b\u6574\u4e2a\u670d\u52a1\u5668\u5171\u4eab\u7684\u552f\u4e00 ID\u3002\u6bcf\u4e2a\u4f7f\u7528\u81ea\u5b9a\u4e49\u7edf\u8ba1\u7c7b\u578b\u7684\u540e\u7aef\u90fd\u4f1a\u7ef4\u62a4\u4e00\u4e2a\u672c\u5730\u7f13\u5b58\uff0c\u7528\u6765\u4fdd\u5b58\u5404\u4e2a\u81ea\u5b9a\u4e49 <code class=\"literal\">PgStat_KindInfo</code> \u7684\u4fe1\u606f\u3002</p>\n<p lang=\"zh\">\u5e94\u5c06\u5b9e\u73b0\u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1\u7c7b\u578b\u7684\u6269\u5c55\u6a21\u5757\u52a0\u5165<a class=\"xref\" href=\"/docs/18/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a>\uff0c\u4ee5\u4fbf\u5728 <span class=\"productname\">PostgreSQL</span> \u542f\u52a8\u671f\u95f4\u5c3d\u65e9\u8f7d\u5165\u3002</p>\n<p lang=\"zh\">\u5c55\u793a\u5982\u4f55\u6ce8\u518c\u5e76\u4f7f\u7528\u81ea\u5b9a\u4e49\u7edf\u8ba1\u4fe1\u606f\u7684\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/injection_points</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#EXTEND-CPP\">36.10.16. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/18/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/18/protocol-overview.html", "method": "same-major semantic node", "sha256": "3f1aa8bd4dbef58e9a82e8cf4c82829a4df7416cfa83dd61c18e9e25060f22da", "language": "zh", "matched_nodes": ["#PROTOCOL-OVERVIEW/div[9]/p[1]/span[2]/span[0]"]}, {"url": "/docs/18/xfunc-c.html", "method": "same-major semantic node", "sha256": "4b35ab16ac85cc22b5c37555941784a2fd0a1b66b507e9dfff9a239102c15e77", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/div[2]/div[0]", "#XFUNC-C/div[10]/div[2]/p[2]", "#XFUNC-C/div[10]/div[3]/div[0]", "#XFUNC-C/div[10]/div[3]/div[2]/p[1]", "#XFUNC-C/div[10]/div[3]/div[3]/p[1]", "#XFUNC-C/div[10]/div[3]/div[3]/p[2]", "#XFUNC-C/div[10]/div[4]/div[0]", "#XFUNC-C/div[10]/div[4]/div[2]/p[1]", "#XFUNC-C/div[10]/div[4]/div[3]/p[1]", "#XFUNC-C/div[10]/div[4]/div[3]/p[2]", "#XFUNC-C/div[10]/div[4]/div[3]/p[3]", "#XFUNC-C/div[10]/div[4]/div[3]/p[4]", "#XFUNC-C/div[10]/div[4]/div[3]/p[5]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[11]/p[10]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[2]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[7]", "#XFUNC-C/div[11]/p[8]", "#XFUNC-C/div[12]/div[7]/p[1]", "#XFUNC-C/div[12]/div[8]/p[1]", "#XFUNC-C/div[12]/p[11]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[14]", "#XFUNC-C/div[12]/p[16]", "#XFUNC-C/div[12]/p[18]", "#XFUNC-C/div[12]/p[19]", "#XFUNC-C/div[12]/p[1]", "#XFUNC-C/div[12]/p[21]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[25]", "#XFUNC-C/div[12]/p[27]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[9]", "#XFUNC-C/div[13]/div[19]/p[1]", "#XFUNC-C/div[13]/p[10]", "#XFUNC-C/div[13]/p[12]", "#XFUNC-C/div[13]/p[13]", "#XFUNC-C/div[13]/p[15]", "#XFUNC-C/div[13]/p[20]", "#XFUNC-C/div[13]/p[22]", "#XFUNC-C/div[13]/p[24]", "#XFUNC-C/div[13]/p[26]", "#XFUNC-C/div[13]/p[28]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[3]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[13]/p[8]", "#XFUNC-C/div[14]/p[1]", "#XFUNC-C/div[14]/p[2]", "#XFUNC-C/div[14]/p[4]", "#XFUNC-C/div[14]/p[6]", "#XFUNC-C/div[15]/div[1]/div[0]", "#XFUNC-C/div[15]/div[1]/p[3]", "#XFUNC-C/div[15]/div[1]/p[5]", "#XFUNC-C/div[15]/div[1]/p[6]", "#XFUNC-C/div[15]/div[1]/p[8]", "#XFUNC-C/div[15]/div[1]/p[9]", "#XFUNC-C/div[15]/div[2]/div[0]", "#XFUNC-C/div[15]/div[2]/p[1]", "#XFUNC-C/div[15]/div[2]/p[3]", "#XFUNC-C/div[15]/div[2]/p[5]", "#XFUNC-C/div[16]/div[1]/div[0]", "#XFUNC-C/div[16]/div[2]/div[0]", "#XFUNC-C/div[16]/div[2]/p[1]", "#XFUNC-C/div[16]/div[2]/p[3]", "#XFUNC-C/div[16]/div[2]/p[5]", "#XFUNC-C/div[16]/div[2]/p[6]", "#XFUNC-C/div[16]/div[2]/p[8]", "#XFUNC-C/div[17]/p[1]", "#XFUNC-C/div[17]/p[3]", "#XFUNC-C/div[17]/p[4]", "#XFUNC-C/div[18]/p[10]", "#XFUNC-C/div[18]/p[12]", "#XFUNC-C/div[18]/p[13]", "#XFUNC-C/div[18]/p[15]", "#XFUNC-C/div[18]/p[16]", "#XFUNC-C/div[18]/p[18]", "#XFUNC-C/div[18]/p[19]", "#XFUNC-C/div[18]/p[1]", "#XFUNC-C/div[18]/p[20]", "#XFUNC-C/div[18]/p[3]", "#XFUNC-C/div[18]/p[4]", "#XFUNC-C/div[18]/p[6]", "#XFUNC-C/div[18]/p[7]", "#XFUNC-C/div[19]/p[10]", "#XFUNC-C/div[19]/p[1]", "#XFUNC-C/div[19]/p[2]", "#XFUNC-C/div[19]/p[4]", "#XFUNC-C/div[19]/p[6]", "#XFUNC-C/div[19]/p[7]", "#XFUNC-C/div[19]/p[8]", "#XFUNC-C/div[19]/p[9]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[12]", "#XFUNC-C/div[1]/dl[0]/dt[13]", "#XFUNC-C/div[1]/dl[0]/dt[14]", "#XFUNC-C/div[1]/dl[0]/dt[15]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[20]/p[2]", "#XFUNC-C/div[20]/p[4]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[12]", "#XFUNC-C/div[5]/p[14]", "#XFUNC-C/div[5]/p[16]", "#XFUNC-C/div[5]/p[18]", "#XFUNC-C/div[5]/p[19]", "#XFUNC-C/div[5]/p[22]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[10]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[17]", "#XFUNC-C/div[7]/p[18]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[20]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[7]", "#XFUNC-C/div[7]/p[8]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/18/description/0": "dynamically-loaded C functions", "/versions/18/facts/0/label": "Kind", "/versions/18/facts/0/value": "Native function language", "/versions/18/facts/1/label": "Trusted", "/versions/18/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "126e9ec2b5157e7be6f2d1aaace3449ca213b73b9f2a7d82748ff9e6afc13a05"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "19": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "POSTGRES", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "label": "19beta4", "major": "19", "channel": "preview", "revision": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86", "source_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86", "catalog_fingerprint": "62fbf1a3689dbe8bf7e6b3372cfe6fbf867581427b3858a94c8419b77a4d2d1d"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://pg.center/docs/19/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 19 English manual", "sha256": "d10924ba0f29357c84d2427c3329e05828e7ebd646444296568b8ee8f230b347", "language": "en", "original_url": "/docs/19/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">36.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-C-DYNLOAD\">36.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/19/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u904d\u5386\u901a\u5f80\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/19/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC_EXT(<em class=\"replaceable\"><code>parameters</code></em>);\n</pre>\n<p lang=\"zh\"><code class=\"literal\">PG_MODULE_MAGIC_EXT</code> \u8fd9\u79cd\u5f62\u5f0f\u5141\u8bb8\u4e3a\u6a21\u5757\u6307\u5b9a\u9644\u52a0\u4fe1\u606f\uff1b\u76ee\u524d\u53ef\u4ee5\u6dfb\u52a0\u540d\u79f0\u548c/\u6216\u7248\u672c\u5b57\u7b26\u4e32\u3002\uff08\u5c06\u6765\u53ef\u80fd\u5141\u8bb8\u66f4\u591a\u5b57\u6bb5\u3002\uff09\u53ef\u4ee5\u5199\u6210\u8fd9\u6837\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC_EXT(\n    .name = \"my_module_name\",\n    .version = \"1.2.3\"\n);\n</pre>\n<p lang=\"zh\">\u4e4b\u540e\uff0c\u540d\u79f0\u548c\u7248\u672c\u53ef\u4ee5\u901a\u8fc7 <code class=\"function\">pg_get_loaded_modules()</code> \u51fd\u6570\u67e5\u770b\u3002\u7248\u672c\u5b57\u7b26\u4e32\u7684\u5177\u4f53\u542b\u4e49\u4e0d\u53d7 <span class=\"productname\">PostgreSQL</span> \u9650\u5236\uff0c\u4f46\u5efa\u8bae\u91c7\u7528\u8bed\u4e49\u5316\u7248\u672c\u89c4\u5219\u3002</p>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u5305\u542b\u4e00\u4e2a\u521d\u59cb\u5316\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code>\u7684\u51fd\u6570\uff0c\u90a3\u4e2a\u51fd\u6570\u5c06\u5728\u52a0\u8f7d\u6587\u4ef6\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u4efb\u4f55\u53c2\u6570\uff0c\u5e94\u8be5\u8fd4\u56devoid\u3002\u76ee\u524d\u6ca1\u6709\u529e\u6cd5\u5378\u8f7d\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-C-BASETYPE\">36.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u5c06\u5b83\u4eec\u4f20\u5165\u51fd\u6570\u548c\u4ece\u51fd\u6570\u4f20\u51fa\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012\u30014 \u6216 8 \u5b57\u8282\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/19/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/19/xaggr.html\" title=\"36.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a036.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u51fd\u6570\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/19/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td lang=\"zh\">\u6587\u672c</td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-V1-CALL-CONV\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-C-V1-CALL-CONV\">36.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u8981\u8c03\u7528\u53e6\u4e00\u4e2a\u7248\u672c-1 \u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">DirectFunctionCall<em class=\"replaceable\"><code>n</code></em>(func, arg1, ..., argn)</code>\u3002\u8fd9\u5728\u4f60\u60f3\u8c03\u7528\u6807\u51c6\u5185\u90e8\u5e93\u4e2d\u5b9a\u4e49\u7684\u51fd\u6570\u65f6\u5c24\u5176\u6709\u7528\uff0c\u56e0\u4e3a\u5b83\u63d0\u4f9b\u4e86\u4e0e\u5176 SQL \u7b7e\u540d\u76f8\u4f3c\u7684\u63a5\u53e3\u3002</p>\n<p lang=\"zh\">\u8fd9\u4e9b\u4fbf\u5229\u51fd\u6570\u4ee5\u53ca\u7c7b\u4f3c\u51fd\u6570\u90fd\u53ef\u4ee5\u5728 <code class=\"filename\">fmgr.h</code> \u4e2d\u627e\u5230\u3002<code class=\"function\">DirectFunctionCall<em class=\"replaceable\"><code>n</code></em></code> \u7cfb\u5217\u628a C \u51fd\u6570\u540d\u4f5c\u4e3a\u5176\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\u53e6\u6709 <code class=\"function\">OidFunctionCall<em class=\"replaceable\"><code>n</code></em></code> \u7b49\u4e00\u4e9b\u53d8\u4f53\uff0c\u5b83\u4eec\u63a5\u6536\u76ee\u6807\u51fd\u6570\u7684 OID\u3002\u6240\u6709\u8fd9\u4e9b\u51fd\u6570\u90fd\u8981\u6c42\u4ee5 <code class=\"type\">Datum</code> \u5f62\u5f0f\u63d0\u4f9b\u51fd\u6570\u53c2\u6570\uff0c\u8fd4\u56de\u503c\u4e5f\u540c\u6837\u662f <code class=\"type\">Datum</code>\u3002\u6ce8\u610f\uff0c\u4f7f\u7528\u8fd9\u4e9b\u4fbf\u5229\u51fd\u6570\u65f6\uff0c\u53c2\u6570\u548c\u7ed3\u679c\u90fd\u4e0d\u80fd\u4e3a NULL\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u8981\u5728 C \u4e2d\u8c03\u7528 <code class=\"function\">starts_with(text, text)</code>\uff0c\u4f60\u53ef\u4ee5\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\u67e5\u5230\u5b83\u7684 C \u5b9e\u73b0\u662f <code class=\"function\">Datum text_starts_with(PG_FUNCTION_ARGS)</code> \u51fd\u6570\u3002\u901a\u5e38\u4f60\u4f1a\u7528 <code class=\"literal\">DirectFunctionCall2(text_starts_with, ...)</code> \u6765\u8c03\u7528\u5b83\u3002\u4e0d\u8fc7\uff0c<code class=\"function\">starts_with(text, text)</code> \u9700\u8981\u6392\u5e8f\u89c4\u5219\u4fe1\u606f\uff0c\u56e0\u6b64\u5982\u679c\u8fd9\u6837\u8c03\u7528\uff0c\u4f1a\u56e0<span class=\"quote\">\u201c<span class=\"quote\">\u65e0\u6cd5\u786e\u5b9a\u5b57\u7b26\u4e32\u6bd4\u8f83\u8be5\u4f7f\u7528\u54ea\u4e00\u79cd\u6392\u5e8f\u89c4\u5219</span>\u201d</span>\u800c\u5931\u8d25\u3002\u4f60\u5fc5\u987b\u6539\u7528 <code class=\"literal\">DirectFunctionCall2Coll(text_starts_with, ...)</code>\uff0c\u5e76\u63d0\u4f9b\u6240\u9700\u7684\u6392\u5e8f\u89c4\u5219\uff0c\u901a\u5e38\u5c31\u662f\u4ece <code class=\"function\">PG_GET_COLLATION()</code> \u4f20\u9012\u8fdb\u6765\uff0c\u5982\u4e0b\u9762\u7684\u793a\u4f8b\u6240\u793a\u3002</p>\n<p lang=\"zh\"><code class=\"filename\">fmgr.h</code> \u8fd8\u63d0\u4f9b\u4e86\u4fbf\u4e8e\u5728 C \u7c7b\u578b\u548c <code class=\"type\">Datum</code> \u4e4b\u95f4\u8f6c\u6362\u7684\u5b8f\u3002\u4f8b\u5982\uff0c\u8981\u628a <code class=\"type\">Datum</code> \u8f6c\u6210 <code class=\"type\">text*</code>\uff0c\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">DatumGetTextPP(X)</code>\u3002\u867d\u7136\u67d0\u4e9b\u7c7b\u578b\u4e3a\u53cd\u5411\u8f6c\u6362\u63d0\u4f9b\u4e86\u540d\u4e3a <code class=\"function\">TypeGetDatum(X)</code> \u4e4b\u7c7b\u7684\u5b8f\uff0c\u4f46 <code class=\"type\">text*</code> \u6ca1\u6709\uff1b\u5bf9\u5b83\u800c\u8a00\uff0c\u76f4\u63a5\u4f7f\u7528\u901a\u7528\u5b8f <code class=\"function\">PointerGetDatum(X)</code> \u5373\u53ef\u3002\u5982\u679c\u4f60\u7684\u6269\u5c55\u5b9a\u4e49\u4e86\u989d\u5916\u7684\u7c7b\u578b\uff0c\u901a\u5e38\u4e5f\u5f88\u65b9\u4fbf\u4e3a\u8fd9\u4e9b\u7c7b\u578b\u5b9a\u4e49\u7c7b\u4f3c\u7684\u5b8f\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n#include \"varatt.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = palloc_object(Point);\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy(VARDATA(new_t),          /* destination */\n           VARDATA_ANY(t),          /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n/* A wrapper around starts_with(text, text) */\n\nPG_FUNCTION_INFO_V1(t_starts_with);\n\nDatum\nt_starts_with(PG_FUNCTION_ARGS)\n{\n    text       *t1 = PG_GETARG_TEXT_PP(0);\n    text       *t2 = PG_GETARG_TEXT_PP(1);\n    Oid         collid = PG_GET_COLLATION();\n    bool        result;\n\n    result = DatumGetBool(DirectFunctionCall2Coll(text_starts_with,\n                                                  collid,\n                                                  PointerGetDatum(t1),\n                                                  PointerGetDatum(t2)));\n    PG_RETURN_BOOL(result);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION t_starts_with(text, text) RETURNS boolean\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 't_starts_with'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/19/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"36.10.9.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a036.10.9\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/19/triggers.html\" title=\"\u7b2c\u00a037\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a037\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/19/plhandler.html\" title=\"\u7b2c\u00a057\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a057\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-CODE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-C-CODE\">36.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/19/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/19/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#DFUNC\">36.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 13.0 \u8d77\u9002\u7528\uff1b\u66f4\u65e9\u7248\u672c\u4f7f\u7528\u7684\u662f <code class=\"filename\">gcc</code> \u7f16\u8bd1\u5668\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <span class=\"application\">GCC</span> \u7684 <code class=\"option\">-fPIC</code>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u7f16\u8bd1\u5668\u9009\u9879\u662f <span class=\"application\">GCC</span> \u7684 <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/19/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-API-ABI-STABILITY-GUIDANCE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-API-ABI-STABILITY-GUIDANCE\">36.10.6. \u670d\u52a1\u5668 API \u548c ABI \u7a33\u5b9a\u6027\u6307\u5357</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u672c\u8282\u5411\u6269\u5c55\u548c\u5176\u4ed6\u670d\u52a1\u5668\u63d2\u4ef6\u7684\u4f5c\u8005\u63d0\u4f9b\u6709\u5173 <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668 API \u4e0e ABI \u7a33\u5b9a\u6027\u7684\u6307\u5bfc\u3002</p>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-GENERAL\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.1.\u00a0\u6982\u8ff0 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">PostgreSQL \u670d\u52a1\u5668\u4e3a\u63d2\u4ef6\u63d0\u4f9b\u4e86\u591a\u4e2a\u8fb9\u754c\u6e05\u6670\u7684 API\uff0c\u4f8b\u5982\u672c\u7ae0\u4ecb\u7ecd\u7684\u51fd\u6570\u7ba1\u7406\u5668 fmgr\u3001SPI\uff08\u7b2c 45 \u7ae0\uff09\u4ee5\u53ca\u4e13\u4e3a\u6269\u5c55\u8bbe\u8ba1\u7684\u5404\u79cd\u94a9\u5b50\u3002\u8fd9\u4e9b\u63a5\u53e3\u7ecf\u8fc7\u8c28\u614e\u7ef4\u62a4\uff0c\u4ee5\u4fdd\u6301\u957f\u671f\u7a33\u5b9a\u6027\u548c\u517c\u5bb9\u6027\u3002\u4e0d\u8fc7\uff0c\u670d\u52a1\u5668\u4e2d\u5168\u90e8\u5168\u5c40\u51fd\u6570\u548c\u53d8\u91cf\u5b9e\u9645\u4e0a\u90fd\u6784\u6210\u4e86\u53ef\u516c\u5f00\u4f7f\u7528\u7684 API\uff0c\u5176\u4e2d\u5927\u90e8\u5206\u5728\u8bbe\u8ba1\u65f6\u5e76\u672a\u8003\u8651\u53ef\u6269\u5c55\u6027\u548c\u957f\u671f\u7a33\u5b9a\u6027\u3002</p>\n<p lang=\"zh\">\u56e0\u6b64\uff0c\u867d\u7136\u4f7f\u7528\u8fd9\u4e9b\u63a5\u53e3\u662f\u5b8c\u5168\u5141\u8bb8\u7684\uff0c\u4f46\u8d8a\u662f\u504f\u79bb\u90a3\u4e9b\u4e45\u7ecf\u5b9e\u8df5\u8003\u9a8c\u7684\u8def\u5f84\uff0c\u5c06\u6765\u9047\u5230 API \u6216 ABI \u517c\u5bb9\u6027\u95ee\u9898\u7684\u53ef\u80fd\u6027\u5c31\u8d8a\u5927\u3002\u9f13\u52b1\u6269\u5c55\u4f5c\u8005\u53cd\u9988\u81ea\u5df1\u7684\u9700\u6c42\uff0c\u4ee5\u4fbf\u968f\u7740\u65f6\u95f4\u63a8\u79fb\u548c\u65b0\u7528\u6cd5\u7684\u51fa\u73b0\uff0c\u67d0\u4e9b\u63a5\u53e3\u80fd\u591f\u88ab\u89c6\u4e3a\u66f4\u7a33\u5b9a\uff0c\u6216\u8005\u53ef\u4ee5\u52a0\u5165\u65b0\u7684\u3001\u8bbe\u8ba1\u66f4\u5b8c\u5584\u7684\u63a5\u53e3\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-API-COMPATIBILITY\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.2.\u00a0API \u517c\u5bb9\u6027 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">API\uff0c\u5373\u5e94\u7528\u7a0b\u5e8f\u7f16\u7a0b\u63a5\u53e3\uff0c\u662f\u7f16\u8bd1\u65f6\u4f7f\u7528\u7684\u63a5\u53e3\u3002</p>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-API-MAJOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.2.1.\u00a0Major Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728 <span class=\"productname\">PostgreSQL</span> \u4e0d\u540c\u4e3b\u7248\u672c\u4e4b\u95f4\uff0c<span class=\"emphasis\"><em>\u4e0d\u627f\u8bfa</em></span> API \u517c\u5bb9\u6027\u3002\u56e0\u6b64\uff0c\u6269\u5c55\u4ee3\u7801\u53ef\u80fd\u9700\u8981\u4fee\u6539\u6e90\u4ee3\u7801\u624d\u80fd\u540c\u65f6\u652f\u6301\u591a\u4e2a\u4e3b\u7248\u672c\u3002\u8fd9\u7c7b\u5dee\u5f02\u901a\u5e38\u53ef\u4ee5\u901a\u8fc7\u9884\u5904\u7406\u5668\u6761\u4ef6\uff08\u4f8b\u5982 <code class=\"literal\">#if PG_VERSION_NUM &gt;= 160000</code>\uff09\u6765\u7ba1\u7406\u3002\u90a3\u4e9b\u4f7f\u7528\u4e86\u8fb9\u754c\u6e05\u6670\u63a5\u53e3\u4e4b\u5916\u80fd\u529b\u7684\u590d\u6742\u6269\u5c55\uff0c\u901a\u5e38\u6bcf\u4e2a\u670d\u52a1\u5668\u4e3b\u7248\u672c\u90fd\u9700\u8981\u505a\u5c11\u91cf\u8fd9\u7c7b\u4fee\u6539\u3002</p>\n</div>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-API-MNINOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.2.2.\u00a0Minor Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u529b\u907f\u514d\u5728\u5c0f\u7248\u672c\u53d1\u5e03\u4e2d\u7834\u574f\u670d\u52a1\u5668 API\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u80fd\u9488\u5bf9\u67d0\u4e2a\u5c0f\u7248\u672c\u7f16\u8bd1\u5e76\u6b63\u5e38\u5de5\u4f5c\u7684\u6269\u5c55\u4ee3\u7801\uff0c\u4e5f\u5e94\u5f53\u80fd\u591f\u9488\u5bf9\u540c\u4e00\u4e3b\u7248\u672c\u7684\u5176\u4ed6\u4efb\u610f\u5c0f\u7248\u672c\uff08\u65e0\u8bba\u8fc7\u53bb\u8fd8\u662f\u5c06\u6765\uff09\u7f16\u8bd1\u5e76\u6b63\u5e38\u5de5\u4f5c\u3002</p>\n<p lang=\"zh\">\u5982\u679c<span class=\"emphasis\"><em>\u786e\u5b9e</em></span>\u9700\u8981\u505a\u51fa\u53d8\u66f4\uff0c\u4e5f\u4f1a\u5728\u8003\u8651\u6269\u5c55\u9700\u6c42\u7684\u524d\u63d0\u4e0b\u8c28\u614e\u7ba1\u7406\u3002\u8fd9\u7c7b\u53d8\u66f4\u4f1a\u5728\u53d1\u5e03\u8bf4\u660e\uff08<a class=\"xref\" href=\"/docs/19/release.html\" title=\"\u9644\u5f55\u00a0E.\u00a0\u53d1\u5e03\u8bf4\u660e\">\u9644\u5f55\u00a0E</a>\uff09\u4e2d\u8fdb\u884c\u8bf4\u660e\u3002</p>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-ABI-COMPATIBILITY\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.3.\u00a0ABI \u517c\u5bb9\u6027 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">ABI\uff0c\u5373\u5e94\u7528\u7a0b\u5e8f\u4e8c\u8fdb\u5236\u63a5\u53e3\uff0c\u662f\u8fd0\u884c\u65f6\u4f7f\u7528\u7684\u63a5\u53e3\u3002</p>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-ABI-MAJOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.3.1.\u00a0Major Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u4e0d\u540c\u4e3b\u7248\u672c\u7684\u670d\u52a1\u5668\u5728 ABI \u4e0a\u662f\u6709\u610f\u4e0d\u517c\u5bb9\u7684\u3002\u56e0\u6b64\uff0c\u4f7f\u7528\u670d\u52a1\u5668 API \u7684\u6269\u5c55\u5fc5\u987b\u9488\u5bf9\u6bcf\u4e00\u4e2a\u4e3b\u7248\u672c\u91cd\u65b0\u7f16\u8bd1\u3002\u5305\u542b <code class=\"literal\">PG_MODULE_MAGIC</code>\uff08\u89c1<a class=\"xref\" href=\"/docs/19/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\uff09\u53ef\u4ee5\u786e\u4fdd\u9488\u5bf9\u67d0\u4e2a\u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u4ee3\u7801\u4f1a\u88ab\u5176\u4ed6\u4e3b\u7248\u672c\u62d2\u7edd\u3002</p>\n</div>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-ABI-MNINOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.3.2.\u00a0Minor Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u529b\u907f\u514d\u5728\u5c0f\u7248\u672c\u53d1\u5e03\u4e2d\u7834\u574f\u670d\u52a1\u5668 ABI\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u9488\u5bf9\u4efb\u610f\u4e00\u4e2a\u5c0f\u7248\u672c\u7f16\u8bd1\u7684\u6269\u5c55\uff0c\u5e94\u5f53\u80fd\u4e0e\u540c\u4e00\u4e3b\u7248\u672c\u8fc7\u53bb\u6216\u5c06\u6765\u7684\u5176\u4ed6\u4efb\u610f\u5c0f\u7248\u672c\u4e00\u8d77\u5de5\u4f5c\u3002</p>\n<p lang=\"zh\">\u5982\u679c<span class=\"emphasis\"><em>\u786e\u5b9e</em></span>\u9700\u8981\u53d8\u66f4\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u91cf\u9009\u62e9\u4fb5\u5165\u6027\u6700\u5c0f\u7684\u65b9\u5f0f\uff0c\u4f8b\u5982\u628a\u65b0\u5b57\u6bb5\u585e\u8fdb\u586b\u5145\u7a7a\u95f4\uff0c\u6216\u8005\u9644\u52a0\u5230\u7ed3\u6784\u4f53\u672b\u5c3e\u3002\u8fd9\u7c7b\u4fee\u6539\u901a\u5e38\u4e0d\u5e94\u5f71\u54cd\u6269\u5c55\uff0c\u9664\u975e\u6269\u5c55\u4f7f\u7528\u4e86\u975e\u5e38\u4e0d\u5bfb\u5e38\u7684\u4ee3\u7801\u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u7136\u800c\uff0c\u5728\u6781\u5c11\u6570\u60c5\u51b5\u4e0b\uff0c\u5373\u4f7f\u662f\u8fd9\u79cd\u975e\u4fb5\u5165\u5f0f\u53d8\u66f4\u4e5f\u53ef\u80fd\u4e0d\u73b0\u5b9e\u751a\u81f3\u4e0d\u53ef\u80fd\u505a\u5230\u3002\u53d1\u751f\u8fd9\u79cd\u60c5\u51b5\u65f6\uff0c\u4e5f\u4f1a\u5728\u8003\u8651\u6269\u5c55\u9700\u6c42\u7684\u524d\u63d0\u4e0b\u8c28\u614e\u7ba1\u7406\u8be5\u53d8\u66f4\u3002\u8fd9\u7c7b\u53d8\u66f4\u540c\u6837\u4f1a\u8bb0\u5f55\u5728\u53d1\u5e03\u8bf4\u660e\uff08<a class=\"xref\" href=\"/docs/19/release.html\" title=\"\u9644\u5f55\u00a0E.\u00a0\u53d1\u5e03\u8bf4\u660e\">\u9644\u5f55\u00a0E</a>\uff09\u4e2d\u3002</p>\n<p lang=\"zh\">\u4f46\u8bf7\u6ce8\u610f\uff0c\u670d\u52a1\u5668\u4e2d\u6709\u5f88\u591a\u90e8\u5206\u5e76\u4e0d\u662f\u4f5c\u4e3a\u53ef\u516c\u5f00\u4f7f\u7528\u7684 API \u6765\u8bbe\u8ba1\u548c\u7ef4\u62a4\u7684\uff08\u800c\u4e14\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u5176\u771f\u5b9e\u8fb9\u754c\u4e5f\u5e76\u4e0d\u6e05\u6670\uff09\u3002\u5982\u679c\u51fa\u73b0\u7d27\u6025\u9700\u6c42\uff0c\u5bf9\u8fd9\u4e9b\u90e8\u5206\u8fdb\u884c\u4fee\u6539\u65f6\uff0c\u81ea\u7136\u4f1a\u6bd4\u4fee\u6539\u90a3\u4e9b\u8fb9\u754c\u6e05\u695a\u4e14\u5e7f\u6cdb\u4f7f\u7528\u7684\u63a5\u53e3\u65f6\u66f4\u5c11\u8003\u8651\u6269\u5c55\u4ee3\u7801\u7684\u517c\u5bb9\u6027\u3002</p>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5728\u7f3a\u4e4f\u81ea\u52a8\u5316\u68c0\u6d4b\u8fd9\u7c7b\u53d8\u5316\u7684\u673a\u5236\u65f6\uff0c\u8fd9\u5e76\u4e0d\u80fd\u6784\u6210\u4e25\u683c\u4fdd\u8bc1\uff1b\u4e0d\u8fc7\u4ece\u5386\u53f2\u4e0a\u770b\uff0c\u8fd9\u79cd\u7834\u574f\u6027\u53d8\u5316\u6781\u4e3a\u7f55\u89c1\u3002</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-COMPOSITE-TYPE-ARGS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-C-COMPOSITE-TYPE-ARGS\">36.10.7. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u51fd\u6570\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURNING-ROWS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-C-RETURNING-ROWS\">36.10.8. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-C-RETURN-SET\">36.10.9. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_INT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-POLYMORPHIC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-C-POLYMORPHIC\">36.10.10. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de<a class=\"xref\" href=\"/docs/19/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"36.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a036.2.5\u00a0\u8282</a>\u4e2d\u63cf\u8ff0\u7684\u591a\u6001\u7c7b\u578b\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-SHARED-ADDIN\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-SHARED-ADDIN\">36.10.11. \u5171\u4eab\u5185\u5b58</a></span></h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u3002\u8981\u505a\u5230\u8fd9\u4e00\u70b9\uff0c\u63d2\u4ef6\u7684\u5171\u4eab\u5e93\u5fc5\u987b\u901a\u8fc7<a class=\"xref\" href=\"/docs/19/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a><a class=\"indexterm\" id=\"id-1.8.3.13.15.2.2.2\" name=\"id-1.8.3.13.15.2.2.2\"></a>\u9884\u52a0\u8f7d\u3002\u8be5\u5171\u4eab\u5e93\u8fd8\u5e94\u5728\u5176 <code class=\"function\">_PG_init</code> \u51fd\u6570\u4e2d\u6ce8\u518c\u56de\u8c03\uff0c\u4ee5\u4fbf\u5728\u7cfb\u7edf\u542f\u52a8\u7684\u5408\u9002\u9636\u6bb5\u521d\u59cb\u5316\u5171\u4eab\u5185\u5b58\u3002\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">typedef struct MyShmemData {\n    LWLock      lock;    /* protects the fields below */\n\n    ... shared memory contents ...\n} MyShmemData;\n\nstatic MyShmemData *MyShmem;    /* pointer to the struct in shared memory */\n\nstatic void my_shmem_request(void *arg);\nstatic void my_shmem_init(void *arg);\n\nconst ShmemCallbacks my_shmem_callbacks = {\n    .request_fn = my_shmem_request,\n    .init_fn = my_shmem_init,\n};\n\n/*\n * Module load callback\n */\nvoid\n_PG_init(void)\n{\n    /*\n     * In order to create our shared memory area, we have to be loaded via\n     * shared_preload_libraries.\n     */\n    if (!process_shared_preload_libraries_in_progress)\n        return;\n\n    /* Register our shared memory needs */\n    RegisterShmemCallbacks(&amp;my_shmem_callbacks);\n}\n\n/* callback to request shmem space */\nstatic void\nmy_shmem_request(void *arg)\n{\n    ShmemRequestStruct(.name = \"My shmem area\",\n                       .size = sizeof(MyShmemData),\n                       .ptr = (void **) &amp;MyShmem,\n        );\n}\n\n/* callback to initialize the contents of the MyShmem area at startup */\nstatic void\nmy_shmem_init(void *arg)\n{\n    int         tranche_id;\n\n    /* Initialize the lock */\n    tranche_id = LWLockNewTrancheId(\"my tranche name\");\n    LWLockInitialize(&amp;MyShmem-&gt;lock, tranche_id);\n\n    ... initialize the rest of MyShmem fields ...\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">request_fn</code> \u56de\u8c03\u4f1a\u5728\u7cfb\u7edf\u542f\u52a8\u671f\u95f4\u3001\u5171\u4eab\u5185\u5b58\u5c1a\u672a\u5206\u914d\u4e4b\u524d\u88ab\u8c03\u7528\u3002\u5b83\u5e94\u5f53\u8c03\u7528 <code class=\"function\">ShmemRequestStruct()</code> \u6765\u767b\u8bb0\u63d2\u4ef6\u7684\u5171\u4eab\u5185\u5b58\u9700\u6c42\u3002\u6ce8\u610f\uff0c<code class=\"function\">ShmemRequestStruct()</code> \u5e76\u4e0d\u4f1a\u7acb\u523b\u5206\u914d\u6216\u521d\u59cb\u5316\u5185\u5b58\uff0c\u5b83\u53ea\u662f\u767b\u8bb0\u7a0d\u540e\u5728\u542f\u52a8\u5e8f\u5217\u4e2d\u8981\u5206\u914d\u7684\u7a7a\u95f4\u3002\u5185\u5b58\u5206\u914d\u5b8c\u6210\u540e\u4f1a\u88ab\u521d\u59cb\u5316\u4e3a\u96f6\u3002\u5bf9\u4e8e\u66f4\u590d\u6742\u7684\u521d\u59cb\u5316\uff0c\u53ef\u8bbe\u7f6e <code class=\"function\">init_fn()</code> \u56de\u8c03\uff1b\u8be5\u56de\u8c03\u4f1a\u5728\u5185\u5b58\u5206\u914d\u5e76\u6e05\u96f6\u4e4b\u540e\u3001\u4f46\u5728\u4efb\u4f55\u5176\u4ed6\u8fdb\u7a0b\u5f00\u59cb\u8fd0\u884c\u4e4b\u524d\u88ab\u8c03\u7528\uff0c\u56e0\u6b64\u4e0d\u9700\u8981\u52a0\u9501\u3002</p>\n<p lang=\"zh\">\u5728 Windows \u4e0a\uff0c<code class=\"function\">attach_fn</code> \u56de\u8c03\u5982\u679c\u5b58\u5728\uff0c\u8fd8\u4f1a\u5728\u6bcf\u6b21\u540e\u7aef\u542f\u52a8\u65f6\u989d\u5916\u88ab\u8c03\u7528\u3002\u5b83\u53ef\u7528\u4e8e\u521d\u59cb\u5316\u4e0e\u5171\u4eab\u5185\u5b58\u533a\u57df\u76f8\u5173\u7684\u5176\u4ed6\u6bcf\u540e\u7aef\u72b6\u6001\uff0c\u800c\u8fd9\u4e9b\u72b6\u6001\u5728\u5176\u4ed6\u7cfb\u7edf\u4e0a\u4f1a\u901a\u8fc7 <code class=\"function\">fork()</code> \u88ab\u7ee7\u627f\u3002</p>\n<p lang=\"zh\">\u5728 <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_stat_statements/pg_stat_statements.c</code> \u91cc\u53ef\u4ee5\u627e\u5230\u4e00\u4e2a\u5206\u914d\u5171\u4eab\u5185\u5b58\u7684\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.2.\u00a0\u4f7f\u7528 <code class=\"function\">ShmemRequestStruct</code> \u5728\u542f\u52a8\u540e\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><code class=\"function\">ShmemRequestStruct()</code> \u4e5f\u53ef\u4ee5\u5728\u7cfb\u7edf\u542f\u52a8\u4e4b\u540e\u8c03\u7528\uff0c\u8fd9\u5bf9\u5141\u8bb8\u5728\u672a\u6307\u5b9a\u4e8e<a class=\"xref\" href=\"/docs/19/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a><a class=\"indexterm\" id=\"id-1.8.3.13.15.3.2.3\" name=\"id-1.8.3.13.15.3.2.3\"></a>\u4e2d\u7684\u63d2\u4ef6\u5e93\u91cc\u505a\u5c11\u91cf\u5206\u914d\u5f88\u6709\u7528\u3002\u4e0d\u8fc7\uff0c\u5728\u542f\u52a8\u4e4b\u540e\uff0c\u5982\u679c\u53ef\u7528\u5171\u4eab\u5185\u5b58\u4e0d\u8db3\uff0c\u5206\u914d\u53ef\u80fd\u4f1a\u5931\u8d25\u3002\u7cfb\u7edf\u4f1a\u4e3a\u542f\u52a8\u540e\u7684\u5206\u914d\u4fdd\u7559\u4e00\u90e8\u5206\u5185\u5b58\uff0c\u4f46\u8fd9\u4e2a\u4fdd\u7559\u91cf\u5f88\u5c0f\u3002</p>\n<p lang=\"zh\">\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5728\u7cfb\u7edf\u542f\u52a8\u540e\u8c03\u7528 RegisterShmemCallbacks() \u4f1a\u62a5\u9519\u3002\u8981\u5728\u542f\u52a8\u540e\u4f7f\u7528\u5b83\uff0c\u5fc5\u987b\u5728\u4f20\u5165\u7684 ShmemCallbacks \u7ed3\u6784\u4f53\u4e2d\u8bbe\u7f6e SHMEM_CALLBACKS_ALLOW_AFTER_STARTUP \u6807\u5fd7\uff0c\u8868\u793a\u5df2\u77e5\u6653\u98ce\u9669\u3002</p>\n<p lang=\"zh\">\u5f53\u5728\u542f\u52a8\u540e\u8c03\u7528 <code class=\"function\">RegisterShmemCallbacks()</code> \u65f6\uff0c\u5b83\u4f1a\u6839\u636e\u8bf7\u6c42\u7684\u5185\u5b58\u533a\u57df\u662f\u5426\u5df2\u7ecf\u7531\u5176\u4ed6\u540e\u7aef\u521d\u59cb\u5316\u8fc7\uff0c\u7acb\u5373\u8c03\u7528\u76f8\u5e94\u7684\u56de\u8c03\u51fd\u6570\u3002\u56de\u8c03\u51fd\u6570\u4f1a\u5728\u6301\u6709\u5185\u90e8\u9501\uff08ShmemIndexLock\uff09\u7684\u60c5\u51b5\u4e0b\u6267\u884c\uff0c\u8fd9\u53ef\u4ee5\u9632\u6b62\u4e24\u4e2a\u540e\u7aef\u540c\u65f6\u5c1d\u8bd5\u521d\u59cb\u5316\u8be5\u5185\u5b58\u533a\u57df\u65f6\u51fa\u73b0\u7ade\u6001\u6761\u4ef6\u3002\u5982\u679c\u5206\u914d\u6216\u521d\u59cb\u5316\u56e0\u4efb\u4f55\u539f\u56e0\u5931\u8d25\uff0c\u8fd9\u4e9b\u5171\u4eab\u5185\u5b58\u533a\u57df\u4f1a\u5904\u4e8e\u5e9f\u5f03\u72b6\u6001\uff1b\u5728\u670d\u52a1\u5668\u91cd\u65b0\u542f\u52a8\u4e4b\u524d\uff0c\u4efb\u4f55\u9644\u52a0\u6216\u91cd\u65b0\u521d\u59cb\u5316\u8fd9\u4e9b\u533a\u57df\u7684\u5c1d\u8bd5\u90fd\u4f1a\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u540e\u7aef\u9644\u52a0\u5230\u5df2\u5206\u914d\u7684\u5171\u4eab\u5185\u5b58\u533a\u57df\u65f6\uff0c\u901a\u5e38\u5fc5\u987b\u5411 ShmemRequestStruct() \u4f20\u5165\u5206\u914d\u8be5\u533a\u57df\u65f6\u4f7f\u7528\u7684\u76f8\u540c\u5927\u5c0f\uff1b\u5927\u5c0f\u4e0d\u5339\u914d\u4f1a\u62a5\u9519\u3002\u5982\u679c\u9644\u52a0\u7684\u540e\u7aef\u4e8b\u5148\u4e0d\u77e5\u9053\u5927\u5c0f\uff0c\u53ef\u4ee5\u6539\u4e3a\u4f20\u5165 SHMEM_ATTACH_UNKNOWN_SIZE\uff0c\u8df3\u8fc7\u6b64\u4ea4\u53c9\u68c0\u67e5\u3002SHMEM_ATTACH_UNKNOWN_SIZE \u53ea\u80fd\u7528\u4e8e\u9644\u52a0\u5230\u5df2\u5b58\u5728\u7684\u533a\u57df\uff1b\u5728\u5206\u914d\u533a\u57df\u4e4b\u524d\u4f7f\u7528\u5b83\u4f1a\u62a5\u9519\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-DYNAMIC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.3.\u00a0\u542f\u52a8\u540e\u5206\u914d\u52a8\u6001\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u4e4b\u540e\u5b8c\u6210\u3002\u4e3a\u6b64\uff0c\u6bcf\u4e2a\u9700\u8981\u4f7f\u7528\u8be5\u5171\u4eab\u5185\u5b58\u7684\u540e\u7aef\u90fd\u5e94\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u83b7\u53d6\u4e00\u4e2a\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">void *GetNamedDSMSegment(const char *name, size_t size,\n                         void (*init_callback) (void *ptr, void *arg),\n                         bool *found, void *arg)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u7ed9\u5b9a\u540d\u79f0\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u5c1a\u4e0d\u5b58\u5728\uff0c\u8be5\u51fd\u6570\u4f1a\u5206\u914d\u8be5\u6bb5\uff0c\u5e76\u4f7f\u7528\u63d0\u4f9b\u7684 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u5bf9\u5176\u8fdb\u884c\u521d\u59cb\u5316\u3002\u5982\u679c\u8be5\u6bb5\u5df2\u7ecf\u7531\u53e6\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8fc7\uff0c\u8be5\u51fd\u6570\u5c31\u53ea\u4f1a\u628a\u73b0\u6709\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u9644\u52a0\u5230\u5f53\u524d\u540e\u7aef\u3002\u5728\u524d\u4e00\u79cd\u60c5\u51b5\u4e0b\uff0c<code class=\"function\">GetNamedDSMSegment</code> \u4f1a\u628a <code class=\"literal\">void *arg</code> \u53c2\u6570\u4f20\u7ed9 <code class=\"function\">init_callback</code>\u3002\u8fd9\u5bf9\u5728\u591a\u4e2a DSM \u6bb5\u4e4b\u95f4\u590d\u7528\u521d\u59cb\u5316\u56de\u8c03\u51fd\u6570\u7279\u522b\u6709\u7528\u3002</p>\n<p lang=\"zh\"><code class=\"function\">GetNamedDSMSegment</code> \u4f1a\u786e\u4fdd\u53ea\u6709\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8be5\u5185\u5b58\u6bb5\uff0c\u800c\u5176\u4ed6\u6240\u6709\u540e\u7aef\u90fd\u4f1a\u83b7\u5f97\u6307\u5411\u540c\u4e00\u5757\u5df2\u5b8c\u5168\u5206\u914d\u5e76\u521d\u59cb\u5316\u597d\u7684\u5185\u5b58\u6bb5\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\"><code class=\"function\">GetNamedDSMSegment</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/test_dsm_registry/test_dsm_registry.c</code>\uff0c\u4f4d\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-LWLOCKS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\">36.10.12. \u8f7b\u91cf\u7ea7\u9501\uff08LWLocks\uff09</h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.12.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLocks\u3002\u4e0e\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u4e00\u6837\uff0c\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\uff0c\u5e76\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\u3002\u6b64\u94a9\u5b50\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8fd9\u786e\u4fdd\u5b58\u5728\u4e00\u4e2a\u540d\u4e3a tranche_name\u3001\u5305\u542b num_lwlocks \u4e2a LWLocks \u7684\u6570\u7ec4\u3002\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u53d6\u5f97\u8be5\u6570\u7ec4\u7684\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">LWLockPadded *GetNamedLWLockTranche(const char *tranche_name)\n</pre>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.12.2.\u00a0\u542f\u52a8\u540e\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u83b7\u53d6 LWLocks \u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u540e\u8fdb\u884c\uff0c\u4e5f\u65e0\u9700\u501f\u52a9 <code class=\"literal\">shmem_request_hook</code>\u3002\u4e3a\u6b64\uff0c\u9996\u5148\u901a\u8fc7\u8c03\u7528\u4e0b\u9762\u7684\u51fd\u6570\u5206\u914d\u4e00\u4e2a <code class=\"literal\">tranche_id</code>\uff1a</p>\n<pre class=\"programlisting\">int LWLockNewTrancheId(const char *name)\n</pre>\n<p lang=\"zh\">\u63a5\u4e0b\u6765\uff0c\u521d\u59cb\u5316\u6bcf\u4e2a LWLock\uff0c\u5e76\u628a\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\uff1a</p>\n<pre class=\"programlisting\">void LWLockInitialize(LWLock *lock, int tranche_id)\n</pre>\n<p lang=\"zh\">\u4e0e\u5171\u4eab\u5185\u5b58\u7c7b\u4f3c\uff0c\u6bcf\u4e2a\u540e\u7aef\u90fd\u5e94\u786e\u4fdd\u53ea\u6709\u4e00\u4e2a\u8fdb\u7a0b\u4f1a\u5206\u914d\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u5e76\u521d\u59cb\u5316\u6bcf\u4e00\u4e2a\u65b0\u7684 LWLock\u3002\u4e00\u79cd\u505a\u6cd5\u662f\u4ec5\u5728\u6301\u6709 <code class=\"function\">AddinShmemInitLock</code> \u72ec\u5360\u9501\u7684\u5171\u4eab\u5185\u5b58\u521d\u59cb\u5316\u4ee3\u7801\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u3002\u5982\u679c\u4f7f\u7528 <code class=\"function\">GetNamedDSMSegment</code>\uff0c\u90a3\u4e48\u5728 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u5c31\u8db3\u4ee5\u907f\u514d\u7ade\u4e89\u6761\u4ef6\u3002</p>\n<p lang=\"zh\"><code class=\"function\">LWLockNewTrancheId</code> \u548c <code class=\"function\">LWLockInitialize</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_prewarm/autoprewarm.c</code>\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-WAIT-EVENTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-ADDIN-WAIT-EVENTS\">36.10.13. \u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u5728\u7b49\u5f85\u4e8b\u4ef6\u7c7b\u578b <code class=\"literal\">Extension</code> \u4e0b\u5b9a\u4e49\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\uff1a</p>\n<pre class=\"programlisting\">uint32 WaitEventExtensionNew(const char *wait_event_name)\n</pre>\n<p lang=\"zh\">\u8be5\u7b49\u5f85\u4e8b\u4ef6\u4f1a\u5173\u8054\u5230\u4e00\u4e2a\u9762\u5411\u7528\u6237\u7684\u81ea\u5b9a\u4e49\u5b57\u7b26\u4e32\u3002\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/worker_spi</code>\uff0c\u4f4d\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n<p lang=\"zh\">\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\u53ef\u4ee5\u5728 <a class=\"link\" href=\"/docs/19/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW\" title=\"27.2.3.\u00a0pg_stat_activity\"><code class=\"structname\">pg_stat_activity</code></a> \u4e2d\u67e5\u770b\uff1a</p>\n<pre class=\"screen\">=# SELECT wait_event_type, wait_event FROM pg_stat_activity\n     WHERE backend_type ~ 'worker_spi';\n wait_event_type |  wait_event\n-----------------+---------------\n Extension       | WorkerSpiMain\n(1 row)\n</pre>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-INJECTION-POINTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-ADDIN-INJECTION-POINTS\">36.10.14. \u6ce8\u5165\u70b9</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7ed9\u5b9a\u540d\u79f0 <code class=\"literal\">name</code> \u7684\u6ce8\u5165\u70b9\u53ef\u901a\u8fc7\u4ee5\u4e0b\u5b8f\u58f0\u660e\uff1a</p>\n<pre class=\"programlisting\">INJECTION_POINT(name, arg);\n</pre>\n<p lang=\"zh\">\u670d\u52a1\u5668\u4ee3\u7801\u4e2d\u5df2\u7ecf\u5728\u82e5\u5e72\u5173\u952e\u4f4d\u7f6e\u58f0\u660e\u4e86\u6ce8\u5165\u70b9\u3002\u65b0\u589e\u6ce8\u5165\u70b9\u540e\uff0c\u9700\u8981\u91cd\u65b0\u7f16\u8bd1\u4ee3\u7801\uff0c\u624d\u80fd\u8ba9\u8be5\u6ce8\u5165\u70b9\u51fa\u73b0\u5728\u4e8c\u8fdb\u5236\u6587\u4ef6\u4e2d\u3002\u7528 C \u8bed\u8a00\u7f16\u5199\u7684\u63d2\u4ef6\u4e5f\u53ef\u4ee5\u4f7f\u7528\u540c\u4e00\u4e2a\u5b8f\u5728\u81ea\u5df1\u7684\u4ee3\u7801\u4e2d\u58f0\u660e\u6ce8\u5165\u70b9\u3002\u6ce8\u5165\u70b9\u540d\u79f0\u5e94\u4f7f\u7528\u5c0f\u5199\u5b57\u6bcd\uff0c\u5e76\u7528\u8fde\u5b57\u7b26\u5206\u9694\u5404\u4e2a\u672f\u8bed\u3002<code class=\"literal\">arg</code> \u662f\u8fd0\u884c\u65f6\u4f20\u7ed9\u56de\u8c03\u7684\u53ef\u9009\u53c2\u6570\u503c\u3002</p>\n<p lang=\"zh\">\u6267\u884c\u6ce8\u5165\u70b9\u53ef\u80fd\u9700\u8981\u5206\u914d\u5c11\u91cf\u5185\u5b58\uff0c\u800c\u8fd9\u53ef\u80fd\u5931\u8d25\u3002\u5982\u679c\u4f60\u9700\u8981\u5728\u4e00\u4e2a\u4e0d\u5141\u8bb8\u52a8\u6001\u5206\u914d\u7684\u4e34\u754c\u533a\u4e2d\u4f7f\u7528\u6ce8\u5165\u70b9\uff0c\u53ef\u4ee5\u91c7\u7528\u4ee5\u4e0b\u4e24\u6b65\u6cd5\uff1a</p>\n<pre class=\"programlisting\">INJECTION_POINT_LOAD(name);\nINJECTION_POINT_CACHED(name, arg);\n</pre>\n<p lang=\"zh\">\u5728\u8fdb\u5165\u4e34\u754c\u533a\u4e4b\u524d\uff0c\u8c03\u7528 <code class=\"function\">INJECTION_POINT_LOAD</code>\u3002\u5b83\u4f1a\u68c0\u67e5\u5171\u4eab\u5185\u5b58\u72b6\u6001\uff0c\u5e76\u5728\u8be5\u6ce8\u5165\u70b9\u5904\u4e8e\u6fc0\u6d3b\u72b6\u6001\u65f6\u628a\u56de\u8c03\u52a0\u8f7d\u5230\u540e\u7aef\u79c1\u6709\u5185\u5b58\u4e2d\u3002\u5728\u4e34\u754c\u533a\u5185\u90e8\uff0c\u518d\u7528 <code class=\"function\">INJECTION_POINT_CACHED</code> \u6765\u6267\u884c\u56de\u8c03\u3002</p>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u4e3a\u4e00\u4e2a\u5df2\u7ecf\u58f0\u660e\u597d\u7684\u6ce8\u5165\u70b9\u9644\u52a0\u56de\u8c03\uff1a</p>\n<pre class=\"programlisting\">extern void InjectionPointAttach(const char *name,\n                                 const char *library,\n                                 const char *function,\n                                 const void *private_data,\n                                 int private_data_size);\n</pre>\n<p lang=\"zh\">name \u662f\u6ce8\u5165\u70b9\u7684\u540d\u79f0\uff1b\u6267\u884c\u5230\u8fbe\u6b64\u6ce8\u5165\u70b9\u65f6\uff0c\u5c06\u6267\u884c\u4ece library \u52a0\u8f7d\u7684\u51fd\u6570\u3002private_data \u662f\u4e00\u5757\u5927\u5c0f\u4e3a private_data_size \u7684\u79c1\u6709\u6570\u636e\u533a\u57df\uff0c\u5728\u6267\u884c\u56de\u8c03\u65f6\u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a <code class=\"literal\">InjectionPointCallback</code> \u7684\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">static void\ncustom_injection_callback(const char *name,\n                          const void *private_data,\n                          void *arg)\n{\n    uint32 wait_event_info = WaitEventInjectionPointNew(name);\n\n    pgstat_report_wait_start(wait_event_info);\n    elog(NOTICE, \"%s: executed custom callback\", name);\n    pgstat_report_wait_end();\n}\n</pre>\n<p lang=\"zh\">\u8fd9\u4e2a\u56de\u8c03\u4f1a\u4ee5 <code class=\"literal\">NOTICE</code> \u7ea7\u522b\u5411\u670d\u52a1\u5668\u9519\u8bef\u65e5\u5fd7\u5199\u5165\u4e00\u6761\u6d88\u606f\uff0c\u4f46\u56de\u8c03\u5b8c\u5168\u53ef\u4ee5\u5b9e\u73b0\u66f4\u590d\u6742\u7684\u903b\u8f91\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u5b9a\u4e49\u201c\u5230\u8fbe\u6ce8\u5165\u70b9\u65f6\u5e94\u6267\u884c\u4ec0\u4e48\u52a8\u4f5c\u201d\u7684\u65b9\u5f0f\uff0c\u662f\u628a\u6d4b\u8bd5\u4ee3\u7801\u76f4\u63a5\u5199\u5728\u5e38\u89c4\u6e90\u4ee3\u7801\u65c1\u8fb9\u3002\u5982\u679c\u8be5\u52a8\u4f5c\u4f9d\u8d56\u4e8e\u52a0\u8f7d\u6a21\u5757\u65e0\u6cd5\u8bbf\u95ee\u7684\u5c40\u90e8\u53d8\u91cf\uff0c\u8fd9\u4f1a\u5f88\u6709\u7528\u3002\u6b64\u65f6\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">IS_INJECTION_POINT_ATTACHED</code> \u5b8f\u6765\u68c0\u67e5\u67d0\u4e2a\u6ce8\u5165\u70b9\u662f\u5426\u5df2\u9644\u52a0\uff0c\u4f8b\u5982\uff1a</p>\n<pre class=\"programlisting\">#ifdef USE_INJECTION_POINTS\nif (IS_INJECTION_POINT_ATTACHED(\"before-foobar\"))\n{\n    /* change a local variable if injection point is attached */\n    local_var = 123;\n\n    /* also execute the callback */\n    INJECTION_POINT_CACHED(\"before-foobar\", NULL);\n}\n#endif\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\uff0c\u9644\u52a0\u5230\u6ce8\u5165\u70b9\u4e0a\u7684\u56de\u8c03\u4e0d\u4f1a\u7531 <code class=\"function\">IS_INJECTION_POINT_ATTACHED</code> \u5b8f\u6267\u884c\u3002\u5982\u679c\u4f60\u60f3\u6267\u884c\u8be5\u56de\u8c03\uff0c\u5c31\u5fc5\u987b\u50cf\u4e0a\u9762\u7684\u793a\u4f8b\u90a3\u6837\u53e6\u5916\u8c03\u7528 <code class=\"function\">INJECTION_POINT_CACHED</code>\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u89e3\u9664\u4e00\u4e2a\u6ce8\u5165\u70b9\uff1a</p>\n<pre class=\"programlisting\">extern bool InjectionPointDetach(const char *name);\n</pre>\n<p lang=\"zh\">\u6210\u529f\u65f6\u8fd4\u56de <code class=\"literal\">true</code>\uff0c\u5426\u5219\u8fd4\u56de <code class=\"literal\">false</code>\u3002</p>\n<p lang=\"zh\">\u4e00\u4e2a\u9644\u52a0\u5230\u6ce8\u5165\u70b9\u7684\u56de\u8c03\u4f1a\u5728\u6240\u6709\u540e\u7aef\u4e2d\u751f\u6548\uff0c\u5305\u62ec\u5728\u8c03\u7528 <code class=\"literal\">InjectionPointAttach</code> \u4e4b\u540e\u624d\u542f\u52a8\u7684\u540e\u7aef\u3002\u5b83\u4f1a\u4e00\u76f4\u4fdd\u6301\u9644\u52a0\u72b6\u6001\uff0c\u76f4\u5230\u670d\u52a1\u5668\u505c\u6b62\uff0c\u6216\u8005\u901a\u8fc7 <code class=\"literal\">InjectionPointDetach</code> \u5c06\u5176\u89e3\u9664\u3002</p>\n<p lang=\"zh\">\u76f8\u5173\u793a\u4f8b\u53ef\u89c1\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">src/test/modules/injection_points</code>\u3002</p>\n<p lang=\"zh\">\u8981\u542f\u7528\u6ce8\u5165\u70b9\uff0c\u4f7f\u7528 configure \u65f6\u9700\u6307\u5b9a --enable-injection-points\uff0c\u4f7f\u7528 Meson \u65f6\u9700\u6307\u5b9a -Dinjection_points=true\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-CUSTOM-CUMULATIVE-STATISTICS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#XFUNC-ADDIN-CUSTOM-CUMULATIVE-STATISTICS\">36.10.15. \u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528 C \u8bed\u8a00\u7f16\u5199\u7684\u63d2\u4ef6\u53ef\u4ee5\u4f7f\u7528\u5728<a class=\"link\" href=\"/docs/19/monitoring-stats.html#MONITORING-STATS-SETUP\" title=\"27.2.1.\u00a0\u7edf\u8ba1\u4fe1\u606f\u6536\u96c6\u914d\u7f6e\">\u7d2f\u8ba1\u7edf\u8ba1\u7cfb\u7edf</a>\u4e2d\u6ce8\u518c\u7684\u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u9996\u5148\uff0c\u5b9a\u4e49\u4e00\u4e2a <code class=\"literal\">PgStat_KindInfo</code>\uff0c\u5176\u4e2d\u5305\u542b\u4e0e\u6240\u6ce8\u518c\u81ea\u5b9a\u4e49\u7c7b\u578b\u76f8\u5173\u7684\u5168\u90e8\u4fe1\u606f\u3002\u4f8b\u5982\uff1a</p>\n<pre class=\"programlisting\">static const PgStat_KindInfo custom_stats = {\n    .name = \"custom_stats\",\n    .fixed_amount = false,\n    .shared_size = sizeof(PgStatShared_Custom),\n    .shared_data_off = offsetof(PgStatShared_Custom, stats),\n    .shared_data_len = sizeof(((PgStatShared_Custom *) 0)-&gt;stats),\n    .pending_size = sizeof(PgStat_StatCustomEntry),\n}\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff0c\u6bcf\u4e2a\u9700\u8981\u4f7f\u7528\u8fd9\u79cd\u81ea\u5b9a\u4e49\u7c7b\u578b\u7684\u540e\u7aef\uff0c\u90fd\u9700\u8981\u4f7f\u7528 <code class=\"literal\">pgstat_register_kind</code> \u6ce8\u518c\u5b83\uff0c\u5e76\u6307\u5b9a\u4e00\u4e2a\u7528\u4e8e\u5b58\u50a8\u8be5\u7c7b\u7edf\u8ba1\u6761\u76ee\u7684\u552f\u4e00 ID\uff1a</p>\n<pre class=\"programlisting\">extern PgStat_Kind pgstat_register_kind(PgStat_Kind kind,\n                                        const PgStat_KindInfo *kind_info);\n</pre>\n<p lang=\"zh\">\u5728\u5f00\u53d1\u65b0\u6269\u5c55\u65f6\uff0c\u5e94\u5c06 <code class=\"literal\">PGSTAT_KIND_EXPERIMENTAL</code> \u7528\u4f5c <em class=\"parameter\"><code>kind</code></em>\u3002\u5f53\u4f60\u51c6\u5907\u628a\u6269\u5c55\u53d1\u5e03\u7ed9\u7528\u6237\u65f6\uff0c\u8bf7\u5728 <a class=\"ulink\" href=\"https://wiki.postgresql.org/wiki/CustomCumulativeStats\" target=\"_top\">Custom Cumulative Statistics</a> \u9875\u9762\u4e0a\u9884\u7559\u4e00\u4e2a kind ID\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e <code class=\"literal\">PgStat_KindInfo</code> API \u7684\u7ec6\u8282\uff0c\u53ef\u89c1 <code class=\"filename\">src/include/utils/pgstat_internal.h</code>\u3002</p>\n<p lang=\"zh\">\u5df2\u6ce8\u518c\u7684\u7edf\u8ba1\u7c7b\u578b\u4f1a\u5173\u8054\u5230\u4e00\u4e2a\u540d\u79f0\u4ee5\u53ca\u4e00\u4e2a\u5728\u5171\u4eab\u5185\u5b58\u4e2d\u4f9b\u6574\u4e2a\u670d\u52a1\u5668\u5171\u4eab\u7684\u552f\u4e00 ID\u3002\u6bcf\u4e2a\u4f7f\u7528\u81ea\u5b9a\u4e49\u7edf\u8ba1\u7c7b\u578b\u7684\u540e\u7aef\u90fd\u4f1a\u7ef4\u62a4\u4e00\u4e2a\u672c\u5730\u7f13\u5b58\uff0c\u7528\u6765\u4fdd\u5b58\u5404\u4e2a\u81ea\u5b9a\u4e49 <code class=\"literal\">PgStat_KindInfo</code> \u7684\u4fe1\u606f\u3002</p>\n<p lang=\"zh\">\u5e94\u5c06\u5b9e\u73b0\u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1\u7c7b\u578b\u7684\u6269\u5c55\u6a21\u5757\u52a0\u5165<a class=\"xref\" href=\"/docs/19/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a>\uff0c\u4ee5\u4fbf\u5728 <span class=\"productname\">PostgreSQL</span> \u542f\u52a8\u671f\u95f4\u5c3d\u65e9\u8f7d\u5165\u3002</p>\n<p lang=\"zh\">\u5c55\u793a\u5982\u4f55\u6ce8\u518c\u5e76\u4f7f\u7528\u81ea\u5b9a\u4e49\u7edf\u8ba1\u4fe1\u606f\u7684\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/test_custom_stats</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/19/xfunc-c.html#EXTEND-CPP\">36.10.16. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern \"C\"</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern \"C\"</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern \"C\"</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/19/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/19/protocol-overview.html", "method": "same-major semantic node", "sha256": "4650a5af6514ccd289c59f90ba62490b00e797ee04c02359ef9e2174c1f276ed", "language": "zh", "matched_nodes": ["#PROTOCOL-OVERVIEW/div[9]/p[1]/span[2]/span[0]"]}, {"url": "/docs/19/xfunc-c.html", "method": "same-major semantic node", "sha256": "280b87b6c75df1c65f4fa4342c909e5e22ef756458232ac785459c8176101153", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/div[2]/div[0]", "#XFUNC-C/div[10]/div[2]/p[2]", "#XFUNC-C/div[10]/div[3]/div[0]", "#XFUNC-C/div[10]/div[3]/div[2]/p[1]", "#XFUNC-C/div[10]/div[3]/div[3]/p[1]", "#XFUNC-C/div[10]/div[3]/div[3]/p[2]", "#XFUNC-C/div[10]/div[4]/div[0]", "#XFUNC-C/div[10]/div[4]/div[2]/p[1]", "#XFUNC-C/div[10]/div[4]/div[3]/p[1]", "#XFUNC-C/div[10]/div[4]/div[3]/p[2]", "#XFUNC-C/div[10]/div[4]/div[3]/p[3]", "#XFUNC-C/div[10]/div[4]/div[3]/p[4]", "#XFUNC-C/div[10]/div[4]/div[3]/p[5]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[11]/p[10]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[2]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[7]", "#XFUNC-C/div[11]/p[8]", "#XFUNC-C/div[12]/div[7]/p[1]", "#XFUNC-C/div[12]/div[8]/p[1]", "#XFUNC-C/div[12]/p[11]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[14]", "#XFUNC-C/div[12]/p[16]", "#XFUNC-C/div[12]/p[18]", "#XFUNC-C/div[12]/p[19]", "#XFUNC-C/div[12]/p[1]", "#XFUNC-C/div[12]/p[21]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[25]", "#XFUNC-C/div[12]/p[27]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[9]", "#XFUNC-C/div[13]/div[19]/p[1]", "#XFUNC-C/div[13]/p[10]", "#XFUNC-C/div[13]/p[12]", "#XFUNC-C/div[13]/p[13]", "#XFUNC-C/div[13]/p[15]", "#XFUNC-C/div[13]/p[20]", "#XFUNC-C/div[13]/p[22]", "#XFUNC-C/div[13]/p[24]", "#XFUNC-C/div[13]/p[26]", "#XFUNC-C/div[13]/p[28]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[3]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[13]/p[8]", "#XFUNC-C/div[14]/p[1]", "#XFUNC-C/div[14]/p[2]", "#XFUNC-C/div[14]/p[4]", "#XFUNC-C/div[14]/p[6]", "#XFUNC-C/div[15]/div[1]/div[0]", "#XFUNC-C/div[15]/div[1]/p[1]", "#XFUNC-C/div[15]/div[1]/p[3]", "#XFUNC-C/div[15]/div[1]/p[4]", "#XFUNC-C/div[15]/div[1]/p[5]", "#XFUNC-C/div[15]/div[2]/div[0]", "#XFUNC-C/div[15]/div[2]/p[1]", "#XFUNC-C/div[15]/div[2]/p[3]", "#XFUNC-C/div[15]/div[3]/div[0]", "#XFUNC-C/div[15]/div[3]/p[1]", "#XFUNC-C/div[15]/div[3]/p[3]", "#XFUNC-C/div[15]/div[3]/p[4]", "#XFUNC-C/div[15]/div[3]/p[5]", "#XFUNC-C/div[16]/div[1]/div[0]", "#XFUNC-C/div[16]/div[2]/div[0]", "#XFUNC-C/div[16]/div[2]/p[1]", "#XFUNC-C/div[16]/div[2]/p[3]", "#XFUNC-C/div[16]/div[2]/p[5]", "#XFUNC-C/div[16]/div[2]/p[6]", "#XFUNC-C/div[17]/p[1]", "#XFUNC-C/div[17]/p[3]", "#XFUNC-C/div[17]/p[4]", "#XFUNC-C/div[18]/p[10]", "#XFUNC-C/div[18]/p[12]", "#XFUNC-C/div[18]/p[13]", "#XFUNC-C/div[18]/p[15]", "#XFUNC-C/div[18]/p[16]", "#XFUNC-C/div[18]/p[18]", "#XFUNC-C/div[18]/p[19]", "#XFUNC-C/div[18]/p[1]", "#XFUNC-C/div[18]/p[20]", "#XFUNC-C/div[18]/p[3]", "#XFUNC-C/div[18]/p[4]", "#XFUNC-C/div[18]/p[6]", "#XFUNC-C/div[18]/p[7]", "#XFUNC-C/div[19]/p[10]", "#XFUNC-C/div[19]/p[1]", "#XFUNC-C/div[19]/p[2]", "#XFUNC-C/div[19]/p[4]", "#XFUNC-C/div[19]/p[6]", "#XFUNC-C/div[19]/p[7]", "#XFUNC-C/div[19]/p[8]", "#XFUNC-C/div[19]/p[9]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[12]", "#XFUNC-C/div[1]/dl[0]/dt[13]", "#XFUNC-C/div[1]/dl[0]/dt[14]", "#XFUNC-C/div[1]/dl[0]/dt[15]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[20]/p[2]", "#XFUNC-C/div[20]/p[4]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[12]", "#XFUNC-C/div[5]/p[14]", "#XFUNC-C/div[5]/p[16]", "#XFUNC-C/div[5]/p[18]", "#XFUNC-C/div[5]/p[19]", "#XFUNC-C/div[5]/p[22]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[10]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[17]", "#XFUNC-C/div[7]/p[18]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[20]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[7]", "#XFUNC-C/div[7]/p[8]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/19/description/0": "dynamically-loaded C functions", "/versions/19/facts/0/label": "Kind", "/versions/19/facts/0/value": "Native function language", "/versions/19/facts/1/label": "Trusted", "/versions/19/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "5319397c4db3e4bfdae9ee6b8cf5cee9d236ad7e694ce5974659042a0630f37e"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "20": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "POSTGRES", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "label": "20devel", "major": "20", "channel": "devel", "revision": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41", "source_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41", "catalog_fingerprint": "398fbb9f262264053c02fbf79f88be0a6770c1473faa6ecd5931d6ec41b8258b", "source_snapshot_utc": "26-Sep-2026 20:22"}, "sources": [{"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://pg.center/docs/devel/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 20 English manual", "sha256": "23cfaf3b2d00552875789ddab73d7fc90d9313fb995c0368f153f979e61fd2e6", "language": "en", "original_url": "/docs/devel/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">36.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-C-DYNLOAD\">36.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/devel/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u904d\u5386\u901a\u5f80\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/devel/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC_EXT(<em class=\"replaceable\"><code>parameters</code></em>);\n</pre>\n<p lang=\"zh\"><code class=\"literal\">PG_MODULE_MAGIC_EXT</code> \u8fd9\u79cd\u5f62\u5f0f\u5141\u8bb8\u4e3a\u6a21\u5757\u6307\u5b9a\u9644\u52a0\u4fe1\u606f\uff1b\u76ee\u524d\u53ef\u4ee5\u6dfb\u52a0\u540d\u79f0\u548c/\u6216\u7248\u672c\u5b57\u7b26\u4e32\u3002\uff08\u5c06\u6765\u53ef\u80fd\u5141\u8bb8\u66f4\u591a\u5b57\u6bb5\u3002\uff09\u53ef\u4ee5\u5199\u6210\u8fd9\u6837\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC_EXT(\n    .name = \"my_module_name\",\n    .version = \"1.2.3\"\n);\n</pre>\n<p lang=\"zh\">\u4e4b\u540e\uff0c\u540d\u79f0\u548c\u7248\u672c\u53ef\u4ee5\u901a\u8fc7 <code class=\"function\">pg_get_loaded_modules()</code> \u51fd\u6570\u67e5\u770b\u3002\u7248\u672c\u5b57\u7b26\u4e32\u7684\u5177\u4f53\u542b\u4e49\u4e0d\u53d7 <span class=\"productname\">PostgreSQL</span> \u9650\u5236\uff0c\u4f46\u5efa\u8bae\u91c7\u7528\u8bed\u4e49\u5316\u7248\u672c\u89c4\u5219\u3002</p>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u5305\u542b\u4e00\u4e2a\u521d\u59cb\u5316\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code>\u7684\u51fd\u6570\uff0c\u90a3\u4e2a\u51fd\u6570\u5c06\u5728\u52a0\u8f7d\u6587\u4ef6\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u4efb\u4f55\u53c2\u6570\uff0c\u5e94\u8be5\u8fd4\u56devoid\u3002\u76ee\u524d\u6ca1\u6709\u529e\u6cd5\u5378\u8f7d\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-C-BASETYPE\">36.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u5c06\u5b83\u4eec\u4f20\u5165\u51fd\u6570\u548c\u4ece\u51fd\u6570\u4f20\u51fa\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012\u30014 \u6216 8 \u5b57\u8282\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/devel/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/devel/xaggr.html\" title=\"36.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a036.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u51fd\u6570\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/devel/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td lang=\"zh\">\u6587\u672c</td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-V1-CALL-CONV\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-C-V1-CALL-CONV\">36.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u8981\u8c03\u7528\u53e6\u4e00\u4e2a\u7248\u672c-1 \u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">DirectFunctionCall<em class=\"replaceable\"><code>n</code></em>(func, arg1, ..., argn)</code>\u3002\u8fd9\u5728\u4f60\u60f3\u8c03\u7528\u6807\u51c6\u5185\u90e8\u5e93\u4e2d\u5b9a\u4e49\u7684\u51fd\u6570\u65f6\u5c24\u5176\u6709\u7528\uff0c\u56e0\u4e3a\u5b83\u63d0\u4f9b\u4e86\u4e0e\u5176 SQL \u7b7e\u540d\u76f8\u4f3c\u7684\u63a5\u53e3\u3002</p>\n<p lang=\"zh\">\u8fd9\u4e9b\u4fbf\u5229\u51fd\u6570\u4ee5\u53ca\u7c7b\u4f3c\u51fd\u6570\u90fd\u53ef\u4ee5\u5728 <code class=\"filename\">fmgr.h</code> \u4e2d\u627e\u5230\u3002<code class=\"function\">DirectFunctionCall<em class=\"replaceable\"><code>n</code></em></code> \u7cfb\u5217\u628a C \u51fd\u6570\u540d\u4f5c\u4e3a\u5176\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\u53e6\u6709 <code class=\"function\">OidFunctionCall<em class=\"replaceable\"><code>n</code></em></code> \u7b49\u4e00\u4e9b\u53d8\u4f53\uff0c\u5b83\u4eec\u63a5\u6536\u76ee\u6807\u51fd\u6570\u7684 OID\u3002\u6240\u6709\u8fd9\u4e9b\u51fd\u6570\u90fd\u8981\u6c42\u4ee5 <code class=\"type\">Datum</code> \u5f62\u5f0f\u63d0\u4f9b\u51fd\u6570\u53c2\u6570\uff0c\u8fd4\u56de\u503c\u4e5f\u540c\u6837\u662f <code class=\"type\">Datum</code>\u3002\u6ce8\u610f\uff0c\u4f7f\u7528\u8fd9\u4e9b\u4fbf\u5229\u51fd\u6570\u65f6\uff0c\u53c2\u6570\u548c\u7ed3\u679c\u90fd\u4e0d\u80fd\u4e3a NULL\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u8981\u5728 C \u4e2d\u8c03\u7528 <code class=\"function\">starts_with(text, text)</code>\uff0c\u4f60\u53ef\u4ee5\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\u67e5\u5230\u5b83\u7684 C \u5b9e\u73b0\u662f <code class=\"function\">Datum text_starts_with(PG_FUNCTION_ARGS)</code> \u51fd\u6570\u3002\u901a\u5e38\u4f60\u4f1a\u7528 <code class=\"literal\">DirectFunctionCall2(text_starts_with, ...)</code> \u6765\u8c03\u7528\u5b83\u3002\u4e0d\u8fc7\uff0c<code class=\"function\">starts_with(text, text)</code> \u9700\u8981\u6392\u5e8f\u89c4\u5219\u4fe1\u606f\uff0c\u56e0\u6b64\u5982\u679c\u8fd9\u6837\u8c03\u7528\uff0c\u4f1a\u56e0<span class=\"quote\">\u201c<span class=\"quote\">\u65e0\u6cd5\u786e\u5b9a\u5b57\u7b26\u4e32\u6bd4\u8f83\u8be5\u4f7f\u7528\u54ea\u4e00\u79cd\u6392\u5e8f\u89c4\u5219</span>\u201d</span>\u800c\u5931\u8d25\u3002\u4f60\u5fc5\u987b\u6539\u7528 <code class=\"literal\">DirectFunctionCall2Coll(text_starts_with, ...)</code>\uff0c\u5e76\u63d0\u4f9b\u6240\u9700\u7684\u6392\u5e8f\u89c4\u5219\uff0c\u901a\u5e38\u5c31\u662f\u4ece <code class=\"function\">PG_GET_COLLATION()</code> \u4f20\u9012\u8fdb\u6765\uff0c\u5982\u4e0b\u9762\u7684\u793a\u4f8b\u6240\u793a\u3002</p>\n<p lang=\"zh\"><code class=\"filename\">fmgr.h</code> \u8fd8\u63d0\u4f9b\u4e86\u4fbf\u4e8e\u5728 C \u7c7b\u578b\u548c <code class=\"type\">Datum</code> \u4e4b\u95f4\u8f6c\u6362\u7684\u5b8f\u3002\u4f8b\u5982\uff0c\u8981\u628a <code class=\"type\">Datum</code> \u8f6c\u6210 <code class=\"type\">text*</code>\uff0c\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">DatumGetTextPP(X)</code>\u3002\u867d\u7136\u67d0\u4e9b\u7c7b\u578b\u4e3a\u53cd\u5411\u8f6c\u6362\u63d0\u4f9b\u4e86\u540d\u4e3a <code class=\"function\">TypeGetDatum(X)</code> \u4e4b\u7c7b\u7684\u5b8f\uff0c\u4f46 <code class=\"type\">text*</code> \u6ca1\u6709\uff1b\u5bf9\u5b83\u800c\u8a00\uff0c\u76f4\u63a5\u4f7f\u7528\u901a\u7528\u5b8f <code class=\"function\">PointerGetDatum(X)</code> \u5373\u53ef\u3002\u5982\u679c\u4f60\u7684\u6269\u5c55\u5b9a\u4e49\u4e86\u989d\u5916\u7684\u7c7b\u578b\uff0c\u901a\u5e38\u4e5f\u5f88\u65b9\u4fbf\u4e3a\u8fd9\u4e9b\u7c7b\u578b\u5b9a\u4e49\u7c7b\u4f3c\u7684\u5b8f\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n#include \"varatt.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = palloc_object(Point);\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy(VARDATA(new_t),          /* destination */\n           VARDATA_ANY(t),          /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n/* A wrapper around starts_with(text, text) */\n\nPG_FUNCTION_INFO_V1(t_starts_with);\n\nDatum\nt_starts_with(PG_FUNCTION_ARGS)\n{\n    text       *t1 = PG_GETARG_TEXT_PP(0);\n    text       *t2 = PG_GETARG_TEXT_PP(1);\n    Oid         collid = PG_GET_COLLATION();\n    bool        result;\n\n    result = DatumGetBool(DirectFunctionCall2Coll(text_starts_with,\n                                                  collid,\n                                                  PointerGetDatum(t1),\n                                                  PointerGetDatum(t2)));\n    PG_RETURN_BOOL(result);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION t_starts_with(text, text) RETURNS boolean\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 't_starts_with'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u5f92\u589e\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/devel/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"36.10.9.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a036.10.9\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/devel/triggers.html\" title=\"\u7b2c\u00a037\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a037\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/devel/plhandler.html\" title=\"\u7b2c\u00a057\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a057\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-CODE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-C-CODE\">36.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/devel/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/devel/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#DFUNC\">36.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 13.0 \u8d77\u9002\u7528\uff1b\u66f4\u65e9\u7248\u672c\u4f7f\u7528\u7684\u662f <code class=\"filename\">gcc</code> \u7f16\u8bd1\u5668\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <span class=\"application\">GCC</span> \u7684 <code class=\"option\">-fPIC</code>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u7f16\u8bd1\u5668\u9009\u9879\u662f <span class=\"application\">GCC</span> \u7684 <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/devel/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-API-ABI-STABILITY-GUIDANCE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-API-ABI-STABILITY-GUIDANCE\">36.10.6. \u670d\u52a1\u5668 API \u548c ABI \u7a33\u5b9a\u6027\u6307\u5357</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u672c\u8282\u5411\u6269\u5c55\u548c\u5176\u4ed6\u670d\u52a1\u5668\u63d2\u4ef6\u7684\u4f5c\u8005\u63d0\u4f9b\u6709\u5173 <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668 API \u4e0e ABI \u7a33\u5b9a\u6027\u7684\u6307\u5bfc\u3002</p>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-GENERAL\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.1.\u00a0\u6982\u8ff0 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">PostgreSQL \u670d\u52a1\u5668\u4e3a\u63d2\u4ef6\u63d0\u4f9b\u4e86\u591a\u4e2a\u8fb9\u754c\u6e05\u6670\u7684 API\uff0c\u4f8b\u5982\u672c\u7ae0\u4ecb\u7ecd\u7684\u51fd\u6570\u7ba1\u7406\u5668 fmgr\u3001SPI\uff08\u7b2c 45 \u7ae0\uff09\u4ee5\u53ca\u4e13\u4e3a\u6269\u5c55\u8bbe\u8ba1\u7684\u5404\u79cd\u94a9\u5b50\u3002\u8fd9\u4e9b\u63a5\u53e3\u7ecf\u8fc7\u8c28\u614e\u7ef4\u62a4\uff0c\u4ee5\u4fdd\u6301\u957f\u671f\u7a33\u5b9a\u6027\u548c\u517c\u5bb9\u6027\u3002\u4e0d\u8fc7\uff0c\u670d\u52a1\u5668\u4e2d\u5168\u90e8\u5168\u5c40\u51fd\u6570\u548c\u53d8\u91cf\u5b9e\u9645\u4e0a\u90fd\u6784\u6210\u4e86\u53ef\u516c\u5f00\u4f7f\u7528\u7684 API\uff0c\u5176\u4e2d\u5927\u90e8\u5206\u5728\u8bbe\u8ba1\u65f6\u5e76\u672a\u8003\u8651\u53ef\u6269\u5c55\u6027\u548c\u957f\u671f\u7a33\u5b9a\u6027\u3002</p>\n<p lang=\"zh\">\u56e0\u6b64\uff0c\u867d\u7136\u4f7f\u7528\u8fd9\u4e9b\u63a5\u53e3\u662f\u5b8c\u5168\u5141\u8bb8\u7684\uff0c\u4f46\u8d8a\u662f\u504f\u79bb\u90a3\u4e9b\u4e45\u7ecf\u5b9e\u8df5\u8003\u9a8c\u7684\u8def\u5f84\uff0c\u5c06\u6765\u9047\u5230 API \u6216 ABI \u517c\u5bb9\u6027\u95ee\u9898\u7684\u53ef\u80fd\u6027\u5c31\u8d8a\u5927\u3002\u9f13\u52b1\u6269\u5c55\u4f5c\u8005\u53cd\u9988\u81ea\u5df1\u7684\u9700\u6c42\uff0c\u4ee5\u4fbf\u968f\u7740\u65f6\u95f4\u63a8\u79fb\u548c\u65b0\u7528\u6cd5\u7684\u51fa\u73b0\uff0c\u67d0\u4e9b\u63a5\u53e3\u80fd\u591f\u88ab\u89c6\u4e3a\u66f4\u7a33\u5b9a\uff0c\u6216\u8005\u53ef\u4ee5\u52a0\u5165\u65b0\u7684\u3001\u8bbe\u8ba1\u66f4\u5b8c\u5584\u7684\u63a5\u53e3\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-API-COMPATIBILITY\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.2.\u00a0API \u517c\u5bb9\u6027 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">API\uff0c\u5373\u5e94\u7528\u7a0b\u5e8f\u7f16\u7a0b\u63a5\u53e3\uff0c\u662f\u7f16\u8bd1\u65f6\u4f7f\u7528\u7684\u63a5\u53e3\u3002</p>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-API-MAJOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.2.1.\u00a0Major Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728 <span class=\"productname\">PostgreSQL</span> \u4e0d\u540c\u4e3b\u7248\u672c\u4e4b\u95f4\uff0c<span class=\"emphasis\"><em>\u4e0d\u627f\u8bfa</em></span> API \u517c\u5bb9\u6027\u3002\u56e0\u6b64\uff0c\u6269\u5c55\u4ee3\u7801\u53ef\u80fd\u9700\u8981\u4fee\u6539\u6e90\u4ee3\u7801\u624d\u80fd\u540c\u65f6\u652f\u6301\u591a\u4e2a\u4e3b\u7248\u672c\u3002\u8fd9\u7c7b\u5dee\u5f02\u901a\u5e38\u53ef\u4ee5\u901a\u8fc7\u9884\u5904\u7406\u5668\u6761\u4ef6\uff08\u4f8b\u5982 <code class=\"literal\">#if PG_VERSION_NUM &gt;= 160000</code>\uff09\u6765\u7ba1\u7406\u3002\u90a3\u4e9b\u4f7f\u7528\u4e86\u8fb9\u754c\u6e05\u6670\u63a5\u53e3\u4e4b\u5916\u80fd\u529b\u7684\u590d\u6742\u6269\u5c55\uff0c\u901a\u5e38\u6bcf\u4e2a\u670d\u52a1\u5668\u4e3b\u7248\u672c\u90fd\u9700\u8981\u505a\u5c11\u91cf\u8fd9\u7c7b\u4fee\u6539\u3002</p>\n</div>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-API-MNINOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.2.2.\u00a0Minor Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u529b\u907f\u514d\u5728\u5c0f\u7248\u672c\u53d1\u5e03\u4e2d\u7834\u574f\u670d\u52a1\u5668 API\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u80fd\u9488\u5bf9\u67d0\u4e2a\u5c0f\u7248\u672c\u7f16\u8bd1\u5e76\u6b63\u5e38\u5de5\u4f5c\u7684\u6269\u5c55\u4ee3\u7801\uff0c\u4e5f\u5e94\u5f53\u80fd\u591f\u9488\u5bf9\u540c\u4e00\u4e3b\u7248\u672c\u7684\u5176\u4ed6\u4efb\u610f\u5c0f\u7248\u672c\uff08\u65e0\u8bba\u8fc7\u53bb\u8fd8\u662f\u5c06\u6765\uff09\u7f16\u8bd1\u5e76\u6b63\u5e38\u5de5\u4f5c\u3002</p>\n<p lang=\"zh\">\u5982\u679c<span class=\"emphasis\"><em>\u786e\u5b9e</em></span>\u9700\u8981\u505a\u51fa\u53d8\u66f4\uff0c\u4e5f\u4f1a\u5728\u8003\u8651\u6269\u5c55\u9700\u6c42\u7684\u524d\u63d0\u4e0b\u8c28\u614e\u7ba1\u7406\u3002\u8fd9\u7c7b\u53d8\u66f4\u4f1a\u5728\u53d1\u5e03\u8bf4\u660e\uff08<a class=\"xref\" href=\"/docs/devel/release.html\" title=\"\u9644\u5f55\u00a0E.\u00a0\u53d1\u5e03\u8bf4\u660e\">\u9644\u5f55\u00a0E</a>\uff09\u4e2d\u8fdb\u884c\u8bf4\u660e\u3002</p>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-ABI-COMPATIBILITY\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.3.\u00a0ABI \u517c\u5bb9\u6027 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">ABI\uff0c\u5373\u5e94\u7528\u7a0b\u5e8f\u4e8c\u8fdb\u5236\u63a5\u53e3\uff0c\u662f\u8fd0\u884c\u65f6\u4f7f\u7528\u7684\u63a5\u53e3\u3002</p>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-ABI-MAJOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.3.1.\u00a0Major Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u4e0d\u540c\u4e3b\u7248\u672c\u7684\u670d\u52a1\u5668\u5728 ABI \u4e0a\u662f\u6709\u610f\u4e0d\u517c\u5bb9\u7684\u3002\u56e0\u6b64\uff0c\u4f7f\u7528\u670d\u52a1\u5668 API \u7684\u6269\u5c55\u5fc5\u987b\u9488\u5bf9\u6bcf\u4e00\u4e2a\u4e3b\u7248\u672c\u91cd\u65b0\u7f16\u8bd1\u3002\u5305\u542b <code class=\"literal\">PG_MODULE_MAGIC</code>\uff08\u89c1<a class=\"xref\" href=\"/docs/devel/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\uff09\u53ef\u4ee5\u786e\u4fdd\u9488\u5bf9\u67d0\u4e2a\u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u4ee3\u7801\u4f1a\u88ab\u5176\u4ed6\u4e3b\u7248\u672c\u62d2\u7edd\u3002</p>\n</div>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-ABI-MNINOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.3.2.\u00a0Minor Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u529b\u907f\u514d\u5728\u5c0f\u7248\u672c\u53d1\u5e03\u4e2d\u7834\u574f\u670d\u52a1\u5668 ABI\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u9488\u5bf9\u4efb\u610f\u4e00\u4e2a\u5c0f\u7248\u672c\u7f16\u8bd1\u7684\u6269\u5c55\uff0c\u5e94\u5f53\u80fd\u4e0e\u540c\u4e00\u4e3b\u7248\u672c\u8fc7\u53bb\u6216\u5c06\u6765\u7684\u5176\u4ed6\u4efb\u610f\u5c0f\u7248\u672c\u4e00\u8d77\u5de5\u4f5c\u3002</p>\n<p lang=\"zh\">\u5982\u679c<span class=\"emphasis\"><em>\u786e\u5b9e</em></span>\u9700\u8981\u53d8\u66f4\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u91cf\u9009\u62e9\u4fb5\u5165\u6027\u6700\u5c0f\u7684\u65b9\u5f0f\uff0c\u4f8b\u5982\u628a\u65b0\u5b57\u6bb5\u585e\u8fdb\u586b\u5145\u7a7a\u95f4\uff0c\u6216\u8005\u9644\u52a0\u5230\u7ed3\u6784\u4f53\u672b\u5c3e\u3002\u8fd9\u7c7b\u4fee\u6539\u901a\u5e38\u4e0d\u5e94\u5f71\u54cd\u6269\u5c55\uff0c\u9664\u975e\u6269\u5c55\u4f7f\u7528\u4e86\u975e\u5e38\u4e0d\u5bfb\u5e38\u7684\u4ee3\u7801\u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u7136\u800c\uff0c\u5728\u6781\u5c11\u6570\u60c5\u51b5\u4e0b\uff0c\u5373\u4f7f\u662f\u8fd9\u79cd\u975e\u4fb5\u5165\u5f0f\u53d8\u66f4\u4e5f\u53ef\u80fd\u4e0d\u73b0\u5b9e\u751a\u81f3\u4e0d\u53ef\u80fd\u505a\u5230\u3002\u53d1\u751f\u8fd9\u79cd\u60c5\u51b5\u65f6\uff0c\u4e5f\u4f1a\u5728\u8003\u8651\u6269\u5c55\u9700\u6c42\u7684\u524d\u63d0\u4e0b\u8c28\u614e\u7ba1\u7406\u8be5\u53d8\u66f4\u3002\u8fd9\u7c7b\u53d8\u66f4\u540c\u6837\u4f1a\u8bb0\u5f55\u5728\u53d1\u5e03\u8bf4\u660e\uff08<a class=\"xref\" href=\"/docs/devel/release.html\" title=\"\u9644\u5f55\u00a0E.\u00a0\u53d1\u5e03\u8bf4\u660e\">\u9644\u5f55\u00a0E</a>\uff09\u4e2d\u3002</p>\n<p lang=\"zh\">\u4f46\u8bf7\u6ce8\u610f\uff0c\u670d\u52a1\u5668\u4e2d\u6709\u5f88\u591a\u90e8\u5206\u5e76\u4e0d\u662f\u4f5c\u4e3a\u53ef\u516c\u5f00\u4f7f\u7528\u7684 API \u6765\u8bbe\u8ba1\u548c\u7ef4\u62a4\u7684\uff08\u800c\u4e14\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u5176\u771f\u5b9e\u8fb9\u754c\u4e5f\u5e76\u4e0d\u6e05\u6670\uff09\u3002\u5982\u679c\u51fa\u73b0\u7d27\u6025\u9700\u6c42\uff0c\u5bf9\u8fd9\u4e9b\u90e8\u5206\u8fdb\u884c\u4fee\u6539\u65f6\uff0c\u81ea\u7136\u4f1a\u6bd4\u4fee\u6539\u90a3\u4e9b\u8fb9\u754c\u6e05\u695a\u4e14\u5e7f\u6cdb\u4f7f\u7528\u7684\u63a5\u53e3\u65f6\u66f4\u5c11\u8003\u8651\u6269\u5c55\u4ee3\u7801\u7684\u517c\u5bb9\u6027\u3002</p>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5728\u7f3a\u4e4f\u81ea\u52a8\u5316\u68c0\u6d4b\u8fd9\u7c7b\u53d8\u5316\u7684\u673a\u5236\u65f6\uff0c\u8fd9\u5e76\u4e0d\u80fd\u6784\u6210\u4e25\u683c\u4fdd\u8bc1\uff1b\u4e0d\u8fc7\u4ece\u5386\u53f2\u4e0a\u770b\uff0c\u8fd9\u79cd\u7834\u574f\u6027\u53d8\u5316\u6781\u4e3a\u7f55\u89c1\u3002</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-COMPOSITE-TYPE-ARGS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-C-COMPOSITE-TYPE-ARGS\">36.10.7. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u51fd\u6570\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURNING-ROWS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-C-RETURNING-ROWS\">36.10.8. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-C-RETURN-SET\">36.10.9. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff08\u5305\u62ec\u7b2c\u4e00\u6b21\uff09\uff0c\u90fd\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_INT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = palloc_array(char *, 3);\n        values[0] = palloc_array(char, 16);\n        values[1] = palloc_array(char, 16);\n        values[2] = palloc_array(char, 16);\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-POLYMORPHIC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-C-POLYMORPHIC\">36.10.10. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de<a class=\"xref\" href=\"/docs/devel/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"36.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a036.2.5\u00a0\u8282</a>\u4e2d\u63cf\u8ff0\u7684\u591a\u6001\u7c7b\u578b\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-SHARED-ADDIN\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-SHARED-ADDIN\">36.10.11. \u5171\u4eab\u5185\u5b58</a></span></h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u3002\u8981\u505a\u5230\u8fd9\u4e00\u70b9\uff0c\u63d2\u4ef6\u7684\u5171\u4eab\u5e93\u5fc5\u987b\u901a\u8fc7<a class=\"xref\" href=\"/docs/devel/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a><a class=\"indexterm\" id=\"id-1.8.3.13.15.2.2.2\" name=\"id-1.8.3.13.15.2.2.2\"></a>\u9884\u52a0\u8f7d\u3002\u8be5\u5171\u4eab\u5e93\u8fd8\u5e94\u5728\u5176 <code class=\"function\">_PG_init</code> \u51fd\u6570\u4e2d\u6ce8\u518c\u56de\u8c03\uff0c\u4ee5\u4fbf\u5728\u7cfb\u7edf\u542f\u52a8\u7684\u5408\u9002\u9636\u6bb5\u521d\u59cb\u5316\u5171\u4eab\u5185\u5b58\u3002\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">typedef struct MyShmemData {\n    LWLock      lock;    /* protects the fields below */\n\n    ... shared memory contents ...\n} MyShmemData;\n\nstatic MyShmemData *MyShmem;    /* pointer to the struct in shared memory */\n\nstatic void my_shmem_request(void *arg);\nstatic void my_shmem_init(void *arg);\n\nconst ShmemCallbacks my_shmem_callbacks = {\n    .request_fn = my_shmem_request,\n    .init_fn = my_shmem_init,\n};\n\n/*\n * Module load callback\n */\nvoid\n_PG_init(void)\n{\n    /*\n     * In order to create our shared memory area, we have to be loaded via\n     * shared_preload_libraries.\n     */\n    if (!process_shared_preload_libraries_in_progress)\n        return;\n\n    /* Register our shared memory needs */\n    RegisterShmemCallbacks(&amp;my_shmem_callbacks);\n}\n\n/* callback to request shmem space */\nstatic void\nmy_shmem_request(void *arg)\n{\n    ShmemRequestStruct(.name = \"My shmem area\",\n                       .size = sizeof(MyShmemData),\n                       .ptr = (void **) &amp;MyShmem,\n        );\n}\n\n/* callback to initialize the contents of the MyShmem area at startup */\nstatic void\nmy_shmem_init(void *arg)\n{\n    int         tranche_id;\n\n    /* Initialize the lock */\n    tranche_id = LWLockNewTrancheId(\"my tranche name\");\n    LWLockInitialize(&amp;MyShmem-&gt;lock, tranche_id);\n\n    ... initialize the rest of MyShmem fields ...\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">request_fn</code> \u56de\u8c03\u4f1a\u5728\u7cfb\u7edf\u542f\u52a8\u671f\u95f4\u3001\u5171\u4eab\u5185\u5b58\u5c1a\u672a\u5206\u914d\u4e4b\u524d\u88ab\u8c03\u7528\u3002\u5b83\u5e94\u5f53\u8c03\u7528 <code class=\"function\">ShmemRequestStruct()</code> \u6765\u767b\u8bb0\u63d2\u4ef6\u7684\u5171\u4eab\u5185\u5b58\u9700\u6c42\u3002\u6ce8\u610f\uff0c<code class=\"function\">ShmemRequestStruct()</code> \u5e76\u4e0d\u4f1a\u7acb\u523b\u5206\u914d\u6216\u521d\u59cb\u5316\u5185\u5b58\uff0c\u5b83\u53ea\u662f\u767b\u8bb0\u7a0d\u540e\u5728\u542f\u52a8\u5e8f\u5217\u4e2d\u8981\u5206\u914d\u7684\u7a7a\u95f4\u3002\u5185\u5b58\u5206\u914d\u5b8c\u6210\u540e\u4f1a\u88ab\u521d\u59cb\u5316\u4e3a\u96f6\u3002\u5bf9\u4e8e\u66f4\u590d\u6742\u7684\u521d\u59cb\u5316\uff0c\u53ef\u8bbe\u7f6e <code class=\"function\">init_fn()</code> \u56de\u8c03\uff1b\u8be5\u56de\u8c03\u4f1a\u5728\u5185\u5b58\u5206\u914d\u5e76\u6e05\u96f6\u4e4b\u540e\u3001\u4f46\u5728\u4efb\u4f55\u5176\u4ed6\u8fdb\u7a0b\u5f00\u59cb\u8fd0\u884c\u4e4b\u524d\u88ab\u8c03\u7528\uff0c\u56e0\u6b64\u4e0d\u9700\u8981\u52a0\u9501\u3002</p>\n<p lang=\"zh\">\u5728 Windows \u4e0a\uff0c<code class=\"function\">attach_fn</code> \u56de\u8c03\u5982\u679c\u5b58\u5728\uff0c\u8fd8\u4f1a\u5728\u6bcf\u6b21\u540e\u7aef\u542f\u52a8\u65f6\u989d\u5916\u88ab\u8c03\u7528\u3002\u5b83\u53ef\u7528\u4e8e\u521d\u59cb\u5316\u4e0e\u5171\u4eab\u5185\u5b58\u533a\u57df\u76f8\u5173\u7684\u5176\u4ed6\u6bcf\u540e\u7aef\u72b6\u6001\uff0c\u800c\u8fd9\u4e9b\u72b6\u6001\u5728\u5176\u4ed6\u7cfb\u7edf\u4e0a\u4f1a\u901a\u8fc7 <code class=\"function\">fork()</code> \u88ab\u7ee7\u627f\u3002</p>\n<p lang=\"zh\">\u5728 <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_stat_statements/pg_stat_statements.c</code> \u91cc\u53ef\u4ee5\u627e\u5230\u4e00\u4e2a\u5206\u914d\u5171\u4eab\u5185\u5b58\u7684\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.2.\u00a0\u4f7f\u7528 <code class=\"function\">ShmemRequestStruct</code> \u5728\u542f\u52a8\u540e\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><code class=\"function\">ShmemRequestStruct()</code> \u4e5f\u53ef\u4ee5\u5728\u7cfb\u7edf\u542f\u52a8\u4e4b\u540e\u8c03\u7528\uff0c\u8fd9\u5bf9\u5141\u8bb8\u5728\u672a\u6307\u5b9a\u4e8e<a class=\"xref\" href=\"/docs/devel/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a><a class=\"indexterm\" id=\"id-1.8.3.13.15.3.2.3\" name=\"id-1.8.3.13.15.3.2.3\"></a>\u4e2d\u7684\u63d2\u4ef6\u5e93\u91cc\u505a\u5c11\u91cf\u5206\u914d\u5f88\u6709\u7528\u3002\u4e0d\u8fc7\uff0c\u5728\u542f\u52a8\u4e4b\u540e\uff0c\u5982\u679c\u53ef\u7528\u5171\u4eab\u5185\u5b58\u4e0d\u8db3\uff0c\u5206\u914d\u53ef\u80fd\u4f1a\u5931\u8d25\u3002\u7cfb\u7edf\u4f1a\u4e3a\u542f\u52a8\u540e\u7684\u5206\u914d\u4fdd\u7559\u4e00\u90e8\u5206\u5185\u5b58\uff0c\u4f46\u8fd9\u4e2a\u4fdd\u7559\u91cf\u5f88\u5c0f\u3002</p>\n<p lang=\"zh\">\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0c\u5728\u7cfb\u7edf\u542f\u52a8\u540e\u8c03\u7528 RegisterShmemCallbacks() \u4f1a\u62a5\u9519\u3002\u8981\u5728\u542f\u52a8\u540e\u4f7f\u7528\u5b83\uff0c\u5fc5\u987b\u5728\u4f20\u5165\u7684 ShmemCallbacks \u7ed3\u6784\u4f53\u4e2d\u8bbe\u7f6e SHMEM_CALLBACKS_ALLOW_AFTER_STARTUP \u6807\u5fd7\uff0c\u8868\u793a\u5df2\u77e5\u6653\u98ce\u9669\u3002</p>\n<p lang=\"zh\">\u5f53\u5728\u542f\u52a8\u540e\u8c03\u7528 <code class=\"function\">RegisterShmemCallbacks()</code> \u65f6\uff0c\u5b83\u4f1a\u6839\u636e\u8bf7\u6c42\u7684\u5185\u5b58\u533a\u57df\u662f\u5426\u5df2\u7ecf\u7531\u5176\u4ed6\u540e\u7aef\u521d\u59cb\u5316\u8fc7\uff0c\u7acb\u5373\u8c03\u7528\u76f8\u5e94\u7684\u56de\u8c03\u51fd\u6570\u3002\u56de\u8c03\u51fd\u6570\u4f1a\u5728\u6301\u6709\u5185\u90e8\u9501\uff08ShmemIndexLock\uff09\u7684\u60c5\u51b5\u4e0b\u6267\u884c\uff0c\u8fd9\u53ef\u4ee5\u9632\u6b62\u4e24\u4e2a\u540e\u7aef\u540c\u65f6\u5c1d\u8bd5\u521d\u59cb\u5316\u8be5\u5185\u5b58\u533a\u57df\u65f6\u51fa\u73b0\u7ade\u6001\u6761\u4ef6\u3002\u5982\u679c\u5206\u914d\u6216\u521d\u59cb\u5316\u56e0\u4efb\u4f55\u539f\u56e0\u5931\u8d25\uff0c\u5171\u4eab\u5185\u5b58\u533a\u57df\u4f1a\u5904\u4e8e\u5e9f\u5f03\u72b6\u6001\uff0c\u76f4\u5230\u670d\u52a1\u5668\u91cd\u542f\u524d\uff0c\u4efb\u4f55\u9644\u52a0\u6216\u91cd\u65b0\u521d\u59cb\u5316\u8fd9\u4e9b\u533a\u57df\u7684\u5c1d\u8bd5\u90fd\u4f1a\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u540e\u7aef\u9644\u52a0\u5230\u5df2\u5206\u914d\u7684\u5171\u4eab\u5185\u5b58\u533a\u57df\u65f6\uff0c\u901a\u5e38\u5fc5\u987b\u5411 ShmemRequestStruct() \u4f20\u5165\u5206\u914d\u8be5\u533a\u57df\u65f6\u4f7f\u7528\u7684\u76f8\u540c\u5927\u5c0f\uff1b\u5927\u5c0f\u4e0d\u5339\u914d\u4f1a\u62a5\u9519\u3002\u5982\u679c\u9644\u52a0\u7684\u540e\u7aef\u4e8b\u5148\u4e0d\u77e5\u9053\u5927\u5c0f\uff0c\u53ef\u4ee5\u6539\u4e3a\u4f20\u5165 SHMEM_ATTACH_UNKNOWN_SIZE\uff0c\u8df3\u8fc7\u6b64\u4ea4\u53c9\u68c0\u67e5\u3002SHMEM_ATTACH_UNKNOWN_SIZE \u53ea\u80fd\u7528\u4e8e\u9644\u52a0\u5230\u5df2\u5b58\u5728\u7684\u533a\u57df\uff1b\u5728\u5206\u914d\u533a\u57df\u4e4b\u524d\u4f7f\u7528\u5b83\u4f1a\u62a5\u9519\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-DYNAMIC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.3.\u00a0\u542f\u52a8\u540e\u5206\u914d\u52a8\u6001\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u4e4b\u540e\u5b8c\u6210\u3002\u4e3a\u6b64\uff0c\u6bcf\u4e2a\u9700\u8981\u4f7f\u7528\u8be5\u5171\u4eab\u5185\u5b58\u7684\u540e\u7aef\u90fd\u5e94\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u83b7\u53d6\u4e00\u4e2a\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">void *GetNamedDSMSegment(const char *name, size_t size,\n                         void (*init_callback) (void *ptr, void *arg),\n                         bool *found, void *arg)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u7ed9\u5b9a\u540d\u79f0\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u5c1a\u4e0d\u5b58\u5728\uff0c\u8be5\u51fd\u6570\u4f1a\u5206\u914d\u8be5\u6bb5\uff0c\u5e76\u4f7f\u7528\u63d0\u4f9b\u7684 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u5bf9\u5176\u8fdb\u884c\u521d\u59cb\u5316\u3002\u5982\u679c\u8be5\u6bb5\u5df2\u7ecf\u7531\u53e6\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8fc7\uff0c\u8be5\u51fd\u6570\u5c31\u53ea\u4f1a\u628a\u73b0\u6709\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u9644\u52a0\u5230\u5f53\u524d\u540e\u7aef\u3002\u5728\u524d\u4e00\u79cd\u60c5\u51b5\u4e0b\uff0c<code class=\"function\">GetNamedDSMSegment</code> \u4f1a\u628a <code class=\"literal\">void *arg</code> \u53c2\u6570\u4f20\u7ed9 <code class=\"function\">init_callback</code>\u3002\u8fd9\u5bf9\u5728\u591a\u4e2a DSM \u6bb5\u4e4b\u95f4\u590d\u7528\u521d\u59cb\u5316\u56de\u8c03\u51fd\u6570\u7279\u522b\u6709\u7528\u3002</p>\n<p lang=\"zh\"><code class=\"function\">GetNamedDSMSegment</code> \u4f1a\u786e\u4fdd\u53ea\u6709\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8be5\u5185\u5b58\u6bb5\uff0c\u800c\u5176\u4ed6\u6240\u6709\u540e\u7aef\u90fd\u4f1a\u83b7\u5f97\u6307\u5411\u540c\u4e00\u5757\u5df2\u5b8c\u5168\u5206\u914d\u5e76\u521d\u59cb\u5316\u597d\u7684\u5185\u5b58\u6bb5\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\"><code class=\"function\">GetNamedDSMSegment</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/test_dsm_registry/test_dsm_registry.c</code>\uff0c\u4f4d\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-LWLOCKS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\">36.10.12. \u8f7b\u91cf\u7ea7\u9501\uff08LWLocks\uff09</h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.12.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLocks\u3002\u4e0e\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u4e00\u6837\uff0c\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\uff0c\u5e76\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\u3002\u6b64\u94a9\u5b50\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8fd9\u786e\u4fdd\u5b58\u5728\u4e00\u4e2a\u540d\u4e3a tranche_name\u3001\u5305\u542b num_lwlocks \u4e2a LWLocks \u7684\u6570\u7ec4\u3002\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u53d6\u5f97\u8be5\u6570\u7ec4\u7684\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">LWLockPadded *GetNamedLWLockTranche(const char *tranche_name)\n</pre>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.12.2.\u00a0\u542f\u52a8\u540e\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u83b7\u53d6 LWLocks \u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u540e\u8fdb\u884c\uff0c\u4e5f\u65e0\u9700\u501f\u52a9 <code class=\"literal\">shmem_request_hook</code>\u3002\u4e3a\u6b64\uff0c\u9996\u5148\u901a\u8fc7\u8c03\u7528\u4e0b\u9762\u7684\u51fd\u6570\u5206\u914d\u4e00\u4e2a <code class=\"literal\">tranche_id</code>\uff1a</p>\n<pre class=\"programlisting\">int LWLockNewTrancheId(const char *name)\n</pre>\n<p lang=\"zh\">\u63a5\u4e0b\u6765\uff0c\u521d\u59cb\u5316\u6bcf\u4e2a LWLock\uff0c\u5e76\u628a\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\uff1a</p>\n<pre class=\"programlisting\">void LWLockInitialize(LWLock *lock, int tranche_id)\n</pre>\n<p lang=\"zh\">\u4e0e\u5171\u4eab\u5185\u5b58\u7c7b\u4f3c\uff0c\u6bcf\u4e2a\u540e\u7aef\u90fd\u5e94\u786e\u4fdd\u53ea\u6709\u4e00\u4e2a\u8fdb\u7a0b\u4f1a\u5206\u914d\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u5e76\u521d\u59cb\u5316\u6bcf\u4e00\u4e2a\u65b0\u7684 LWLock\u3002\u4e00\u79cd\u505a\u6cd5\u662f\u4ec5\u5728\u6301\u6709 <code class=\"function\">AddinShmemInitLock</code> \u72ec\u5360\u9501\u7684\u5171\u4eab\u5185\u5b58\u521d\u59cb\u5316\u4ee3\u7801\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u3002\u5982\u679c\u4f7f\u7528 <code class=\"function\">GetNamedDSMSegment</code>\uff0c\u90a3\u4e48\u5728 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u5c31\u8db3\u4ee5\u907f\u514d\u7ade\u4e89\u6761\u4ef6\u3002</p>\n<p lang=\"zh\"><code class=\"function\">LWLockNewTrancheId</code> \u548c <code class=\"function\">LWLockInitialize</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_prewarm/autoprewarm.c</code>\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-WAIT-EVENTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-ADDIN-WAIT-EVENTS\">36.10.13. \u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u5728\u7b49\u5f85\u4e8b\u4ef6\u7c7b\u578b <code class=\"literal\">Extension</code> \u4e0b\u5b9a\u4e49\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\uff1a</p>\n<pre class=\"programlisting\">uint32 WaitEventExtensionNew(const char *wait_event_name)\n</pre>\n<p lang=\"zh\">\u8be5\u7b49\u5f85\u4e8b\u4ef6\u4f1a\u5173\u8054\u5230\u4e00\u4e2a\u9762\u5411\u7528\u6237\u7684\u81ea\u5b9a\u4e49\u5b57\u7b26\u4e32\u3002\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/worker_spi</code>\uff0c\u4f4d\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n<p lang=\"zh\">\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\u53ef\u4ee5\u5728 <a class=\"link\" href=\"/docs/devel/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW\" title=\"27.2.3.\u00a0pg_stat_activity\"><code class=\"structname\">pg_stat_activity</code></a> \u4e2d\u67e5\u770b\uff1a</p>\n<pre class=\"screen\">=# SELECT wait_event_type, wait_event FROM pg_stat_activity\n     WHERE backend_type ~ 'worker_spi';\n wait_event_type |  wait_event\n-----------------+---------------\n Extension       | WorkerSpiMain\n(1 row)\n</pre>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-INJECTION-POINTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-ADDIN-INJECTION-POINTS\">36.10.14. \u6ce8\u5165\u70b9</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7ed9\u5b9a\u540d\u79f0 <code class=\"literal\">name</code> \u7684\u6ce8\u5165\u70b9\u53ef\u901a\u8fc7\u4ee5\u4e0b\u5b8f\u58f0\u660e\uff1a</p>\n<pre class=\"programlisting\">INJECTION_POINT(name, arg);\n</pre>\n<p lang=\"zh\">\u670d\u52a1\u5668\u4ee3\u7801\u4e2d\u5df2\u7ecf\u5728\u82e5\u5e72\u5173\u952e\u4f4d\u7f6e\u58f0\u660e\u4e86\u6ce8\u5165\u70b9\u3002\u65b0\u589e\u6ce8\u5165\u70b9\u540e\uff0c\u9700\u8981\u91cd\u65b0\u7f16\u8bd1\u4ee3\u7801\uff0c\u624d\u80fd\u8ba9\u8be5\u6ce8\u5165\u70b9\u51fa\u73b0\u5728\u4e8c\u8fdb\u5236\u6587\u4ef6\u4e2d\u3002\u7528 C \u8bed\u8a00\u7f16\u5199\u7684\u63d2\u4ef6\u4e5f\u53ef\u4ee5\u4f7f\u7528\u540c\u4e00\u4e2a\u5b8f\u5728\u81ea\u5df1\u7684\u4ee3\u7801\u4e2d\u58f0\u660e\u6ce8\u5165\u70b9\u3002\u6ce8\u5165\u70b9\u540d\u79f0\u5e94\u4f7f\u7528\u5c0f\u5199\u5b57\u6bcd\uff0c\u5e76\u7528\u8fde\u5b57\u7b26\u5206\u9694\u5404\u4e2a\u672f\u8bed\u3002<code class=\"literal\">arg</code> \u662f\u8fd0\u884c\u65f6\u4f20\u7ed9\u56de\u8c03\u7684\u53ef\u9009\u53c2\u6570\u503c\u3002</p>\n<p lang=\"zh\">\u6267\u884c\u6ce8\u5165\u70b9\u53ef\u80fd\u9700\u8981\u5206\u914d\u5c11\u91cf\u5185\u5b58\uff0c\u800c\u8fd9\u53ef\u80fd\u5931\u8d25\u3002\u5982\u679c\u4f60\u9700\u8981\u5728\u4e00\u4e2a\u4e0d\u5141\u8bb8\u52a8\u6001\u5206\u914d\u7684\u4e34\u754c\u533a\u4e2d\u4f7f\u7528\u6ce8\u5165\u70b9\uff0c\u53ef\u4ee5\u91c7\u7528\u4ee5\u4e0b\u4e24\u6b65\u6cd5\uff1a</p>\n<pre class=\"programlisting\">INJECTION_POINT_LOAD(name);\nINJECTION_POINT_CACHED(name, arg);\n</pre>\n<p lang=\"zh\">\u5728\u8fdb\u5165\u4e34\u754c\u533a\u4e4b\u524d\uff0c\u8c03\u7528 <code class=\"function\">INJECTION_POINT_LOAD</code>\u3002\u5b83\u4f1a\u68c0\u67e5\u5171\u4eab\u5185\u5b58\u72b6\u6001\uff0c\u5e76\u5728\u8be5\u6ce8\u5165\u70b9\u5904\u4e8e\u6fc0\u6d3b\u72b6\u6001\u65f6\u628a\u56de\u8c03\u52a0\u8f7d\u5230\u540e\u7aef\u79c1\u6709\u5185\u5b58\u4e2d\u3002\u5728\u4e34\u754c\u533a\u5185\u90e8\uff0c\u518d\u7528 <code class=\"function\">INJECTION_POINT_CACHED</code> \u6765\u6267\u884c\u56de\u8c03\u3002</p>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u4e3a\u4e00\u4e2a\u5df2\u7ecf\u58f0\u660e\u597d\u7684\u6ce8\u5165\u70b9\u9644\u52a0\u56de\u8c03\uff1a</p>\n<pre class=\"programlisting\">extern void InjectionPointAttach(const char *name,\n                                 const char *library,\n                                 const char *function,\n                                 const void *private_data,\n                                 int private_data_size);\n</pre>\n<p lang=\"zh\">name \u662f\u6ce8\u5165\u70b9\u7684\u540d\u79f0\uff1b\u6267\u884c\u5230\u8fbe\u6b64\u6ce8\u5165\u70b9\u65f6\uff0c\u5c06\u6267\u884c\u4ece library \u52a0\u8f7d\u7684\u51fd\u6570\u3002private_data \u662f\u4e00\u5757\u5927\u5c0f\u4e3a private_data_size \u7684\u79c1\u6709\u6570\u636e\u533a\u57df\uff0c\u5728\u6267\u884c\u56de\u8c03\u65f6\u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a <code class=\"literal\">InjectionPointCallback</code> \u7684\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">static void\ncustom_injection_callback(const char *name,\n                          const void *private_data,\n                          void *arg)\n{\n    uint32 wait_event_info = WaitEventInjectionPointNew(name);\n\n    pgstat_report_wait_start(wait_event_info);\n    elog(NOTICE, \"%s: executed custom callback\", name);\n    pgstat_report_wait_end();\n}\n</pre>\n<p lang=\"zh\">\u8fd9\u4e2a\u56de\u8c03\u4f1a\u4ee5 <code class=\"literal\">NOTICE</code> \u7ea7\u522b\u5411\u670d\u52a1\u5668\u9519\u8bef\u65e5\u5fd7\u5199\u5165\u4e00\u6761\u6d88\u606f\uff0c\u4f46\u56de\u8c03\u5b8c\u5168\u53ef\u4ee5\u5b9e\u73b0\u66f4\u590d\u6742\u7684\u903b\u8f91\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u5b9a\u4e49\u201c\u5230\u8fbe\u6ce8\u5165\u70b9\u65f6\u5e94\u6267\u884c\u4ec0\u4e48\u52a8\u4f5c\u201d\u7684\u65b9\u5f0f\uff0c\u662f\u628a\u6d4b\u8bd5\u4ee3\u7801\u76f4\u63a5\u5199\u5728\u5e38\u89c4\u6e90\u4ee3\u7801\u65c1\u8fb9\u3002\u5982\u679c\u8be5\u52a8\u4f5c\u4f9d\u8d56\u4e8e\u52a0\u8f7d\u6a21\u5757\u65e0\u6cd5\u8bbf\u95ee\u7684\u5c40\u90e8\u53d8\u91cf\uff0c\u8fd9\u4f1a\u5f88\u6709\u7528\u3002\u6b64\u65f6\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">IS_INJECTION_POINT_ATTACHED</code> \u5b8f\u6765\u68c0\u67e5\u67d0\u4e2a\u6ce8\u5165\u70b9\u662f\u5426\u5df2\u9644\u52a0\uff0c\u4f8b\u5982\uff1a</p>\n<pre class=\"programlisting\">#ifdef USE_INJECTION_POINTS\nif (IS_INJECTION_POINT_ATTACHED(\"before-foobar\"))\n{\n    /* change a local variable if injection point is attached */\n    local_var = 123;\n\n    /* also execute the callback */\n    INJECTION_POINT_CACHED(\"before-foobar\", NULL);\n}\n#endif\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\uff0c\u9644\u52a0\u5230\u6ce8\u5165\u70b9\u4e0a\u7684\u56de\u8c03\u4e0d\u4f1a\u7531 <code class=\"function\">IS_INJECTION_POINT_ATTACHED</code> \u5b8f\u6267\u884c\u3002\u5982\u679c\u4f60\u60f3\u6267\u884c\u8be5\u56de\u8c03\uff0c\u5c31\u5fc5\u987b\u50cf\u4e0a\u9762\u7684\u793a\u4f8b\u90a3\u6837\u53e6\u5916\u8c03\u7528 <code class=\"function\">INJECTION_POINT_CACHED</code>\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u89e3\u9664\u4e00\u4e2a\u6ce8\u5165\u70b9\uff1a</p>\n<pre class=\"programlisting\">extern bool InjectionPointDetach(const char *name);\n</pre>\n<p lang=\"zh\">\u6210\u529f\u65f6\u8fd4\u56de <code class=\"literal\">true</code>\uff0c\u5426\u5219\u8fd4\u56de <code class=\"literal\">false</code>\u3002</p>\n<p lang=\"zh\">\u4e00\u4e2a\u9644\u52a0\u5230\u6ce8\u5165\u70b9\u7684\u56de\u8c03\u4f1a\u5728\u6240\u6709\u540e\u7aef\u4e2d\u751f\u6548\uff0c\u5305\u62ec\u5728\u8c03\u7528 <code class=\"literal\">InjectionPointAttach</code> \u4e4b\u540e\u624d\u542f\u52a8\u7684\u540e\u7aef\u3002\u5b83\u4f1a\u4e00\u76f4\u4fdd\u6301\u9644\u52a0\u72b6\u6001\uff0c\u76f4\u5230\u670d\u52a1\u5668\u505c\u6b62\uff0c\u6216\u8005\u901a\u8fc7 <code class=\"literal\">InjectionPointDetach</code> \u5c06\u5176\u89e3\u9664\u3002</p>\n<p lang=\"zh\">\u76f8\u5173\u793a\u4f8b\u53ef\u89c1\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">src/test/modules/injection_points</code>\u3002</p>\n<p lang=\"zh\">\u8981\u542f\u7528\u6ce8\u5165\u70b9\uff0c\u4f7f\u7528 configure \u65f6\u9700\u6307\u5b9a --enable-injection-points\uff0c\u4f7f\u7528 Meson \u65f6\u9700\u6307\u5b9a -Dinjection_points=true\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-CUSTOM-CUMULATIVE-STATISTICS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#XFUNC-ADDIN-CUSTOM-CUMULATIVE-STATISTICS\">36.10.15. \u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528 C \u8bed\u8a00\u7f16\u5199\u7684\u63d2\u4ef6\u53ef\u4ee5\u4f7f\u7528\u5728<a class=\"link\" href=\"/docs/devel/monitoring-stats.html#MONITORING-STATS-SETUP\" title=\"27.2.1.\u00a0\u7edf\u8ba1\u4fe1\u606f\u6536\u96c6\u914d\u7f6e\">\u7d2f\u8ba1\u7edf\u8ba1\u7cfb\u7edf</a>\u4e2d\u6ce8\u518c\u7684\u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u9996\u5148\uff0c\u5b9a\u4e49\u4e00\u4e2a <code class=\"literal\">PgStat_KindInfo</code>\uff0c\u5176\u4e2d\u5305\u542b\u4e0e\u6240\u6ce8\u518c\u81ea\u5b9a\u4e49\u7c7b\u578b\u76f8\u5173\u7684\u5168\u90e8\u4fe1\u606f\u3002\u4f8b\u5982\uff1a</p>\n<pre class=\"programlisting\">static const PgStat_KindInfo custom_stats = {\n    .name = \"custom_stats\",\n    .fixed_amount = false,\n    .shared_size = sizeof(PgStatShared_Custom),\n    .shared_data_off = offsetof(PgStatShared_Custom, stats),\n    .shared_data_len = sizeof(((PgStatShared_Custom *) 0)-&gt;stats),\n    .pending_size = sizeof(PgStat_StatCustomEntry),\n}\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff0c\u6bcf\u4e2a\u9700\u8981\u4f7f\u7528\u8fd9\u79cd\u81ea\u5b9a\u4e49\u7c7b\u578b\u7684\u540e\u7aef\uff0c\u90fd\u9700\u8981\u4f7f\u7528 <code class=\"literal\">pgstat_register_kind</code> \u6ce8\u518c\u5b83\uff0c\u5e76\u6307\u5b9a\u4e00\u4e2a\u7528\u4e8e\u5b58\u50a8\u8be5\u7c7b\u7edf\u8ba1\u6761\u76ee\u7684\u552f\u4e00 ID\uff1a</p>\n<pre class=\"programlisting\">extern PgStat_Kind pgstat_register_kind(PgStat_Kind kind,\n                                        const PgStat_KindInfo *kind_info);\n</pre>\n<p lang=\"zh\">\u5728\u5f00\u53d1\u65b0\u6269\u5c55\u65f6\uff0c\u5e94\u5c06 <code class=\"literal\">PGSTAT_KIND_EXPERIMENTAL</code> \u7528\u4f5c <em class=\"parameter\"><code>kind</code></em>\u3002\u5f53\u4f60\u51c6\u5907\u628a\u6269\u5c55\u53d1\u5e03\u7ed9\u7528\u6237\u65f6\uff0c\u8bf7\u5728 <a class=\"ulink\" href=\"https://wiki.postgresql.org/wiki/CustomCumulativeStats\" target=\"_top\">Custom Cumulative Statistics</a> \u9875\u9762\u4e0a\u9884\u7559\u4e00\u4e2a kind ID\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e <code class=\"literal\">PgStat_KindInfo</code> API \u7684\u7ec6\u8282\uff0c\u53ef\u89c1 <code class=\"filename\">src/include/utils/pgstat_internal.h</code>\u3002</p>\n<p lang=\"zh\">\u5df2\u6ce8\u518c\u7684\u7edf\u8ba1\u7c7b\u578b\u4f1a\u5173\u8054\u5230\u4e00\u4e2a\u540d\u79f0\u4ee5\u53ca\u4e00\u4e2a\u5728\u5171\u4eab\u5185\u5b58\u4e2d\u4f9b\u6574\u4e2a\u670d\u52a1\u5668\u5171\u4eab\u7684\u552f\u4e00 ID\u3002\u6bcf\u4e2a\u4f7f\u7528\u81ea\u5b9a\u4e49\u7edf\u8ba1\u7c7b\u578b\u7684\u540e\u7aef\u90fd\u4f1a\u7ef4\u62a4\u4e00\u4e2a\u672c\u5730\u7f13\u5b58\uff0c\u7528\u6765\u4fdd\u5b58\u5404\u4e2a\u81ea\u5b9a\u4e49 <code class=\"literal\">PgStat_KindInfo</code> \u7684\u4fe1\u606f\u3002</p>\n<p lang=\"zh\">\u5e94\u5c06\u5b9e\u73b0\u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1\u7c7b\u578b\u7684\u6269\u5c55\u6a21\u5757\u52a0\u5165<a class=\"xref\" href=\"/docs/devel/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a>\uff0c\u4ee5\u4fbf\u5728 <span class=\"productname\">PostgreSQL</span> \u542f\u52a8\u671f\u95f4\u5c3d\u65e9\u8f7d\u5165\u3002</p>\n<p lang=\"zh\">\u5c55\u793a\u5982\u4f55\u6ce8\u518c\u5e76\u4f7f\u7528\u81ea\u5b9a\u4e49\u7edf\u8ba1\u4fe1\u606f\u7684\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/test_custom_stats</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/devel/xfunc-c.html#EXTEND-CPP\">36.10.16. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern \"C\"</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern \"C\"</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u9694\u79bb\u5728\u4e00\u5c42\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern \"C\"</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/devel/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/devel/protocol-overview.html", "method": "same-major semantic node", "sha256": "fe7aff6a941aef6be4870c7704bca095984a81fd5019f420b67c9917f3831028", "language": "zh", "matched_nodes": ["#PROTOCOL-OVERVIEW/div[9]/p[1]/span[2]/span[0]"]}, {"url": "/docs/devel/xfunc-c.html", "method": "same-major semantic node", "sha256": "19a7606d054b83bc9a0d8643e200db180e0d278d67acfdd6d5f84e3b3a3e4db7", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/div[2]/div[0]", "#XFUNC-C/div[10]/div[2]/p[2]", "#XFUNC-C/div[10]/div[3]/div[0]", "#XFUNC-C/div[10]/div[3]/div[2]/p[1]", "#XFUNC-C/div[10]/div[3]/div[3]/p[1]", "#XFUNC-C/div[10]/div[3]/div[3]/p[2]", "#XFUNC-C/div[10]/div[4]/div[0]", "#XFUNC-C/div[10]/div[4]/div[2]/p[1]", "#XFUNC-C/div[10]/div[4]/div[3]/p[1]", "#XFUNC-C/div[10]/div[4]/div[3]/p[2]", "#XFUNC-C/div[10]/div[4]/div[3]/p[3]", "#XFUNC-C/div[10]/div[4]/div[3]/p[4]", "#XFUNC-C/div[10]/div[4]/div[3]/p[5]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[11]/p[10]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[2]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[7]", "#XFUNC-C/div[11]/p[8]", "#XFUNC-C/div[12]/div[7]/p[1]", "#XFUNC-C/div[12]/div[8]/p[1]", "#XFUNC-C/div[12]/p[11]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[14]", "#XFUNC-C/div[12]/p[16]", "#XFUNC-C/div[12]/p[18]", "#XFUNC-C/div[12]/p[19]", "#XFUNC-C/div[12]/p[1]", "#XFUNC-C/div[12]/p[21]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[25]", "#XFUNC-C/div[12]/p[27]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[9]", "#XFUNC-C/div[13]/div[19]/p[1]", "#XFUNC-C/div[13]/p[10]", "#XFUNC-C/div[13]/p[12]", "#XFUNC-C/div[13]/p[13]", "#XFUNC-C/div[13]/p[15]", "#XFUNC-C/div[13]/p[20]", "#XFUNC-C/div[13]/p[22]", "#XFUNC-C/div[13]/p[24]", "#XFUNC-C/div[13]/p[26]", "#XFUNC-C/div[13]/p[28]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[3]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[13]/p[8]", "#XFUNC-C/div[14]/p[1]", "#XFUNC-C/div[14]/p[2]", "#XFUNC-C/div[14]/p[4]", "#XFUNC-C/div[14]/p[6]", "#XFUNC-C/div[15]/div[1]/div[0]", "#XFUNC-C/div[15]/div[1]/p[1]", "#XFUNC-C/div[15]/div[1]/p[3]", "#XFUNC-C/div[15]/div[1]/p[4]", "#XFUNC-C/div[15]/div[1]/p[5]", "#XFUNC-C/div[15]/div[2]/div[0]", "#XFUNC-C/div[15]/div[2]/p[1]", "#XFUNC-C/div[15]/div[2]/p[3]", "#XFUNC-C/div[15]/div[3]/div[0]", "#XFUNC-C/div[15]/div[3]/p[1]", "#XFUNC-C/div[15]/div[3]/p[3]", "#XFUNC-C/div[15]/div[3]/p[4]", "#XFUNC-C/div[15]/div[3]/p[5]", "#XFUNC-C/div[16]/div[1]/div[0]", "#XFUNC-C/div[16]/div[2]/div[0]", "#XFUNC-C/div[16]/div[2]/p[1]", "#XFUNC-C/div[16]/div[2]/p[3]", "#XFUNC-C/div[16]/div[2]/p[5]", "#XFUNC-C/div[16]/div[2]/p[6]", "#XFUNC-C/div[17]/p[1]", "#XFUNC-C/div[17]/p[3]", "#XFUNC-C/div[17]/p[4]", "#XFUNC-C/div[18]/p[10]", "#XFUNC-C/div[18]/p[12]", "#XFUNC-C/div[18]/p[13]", "#XFUNC-C/div[18]/p[15]", "#XFUNC-C/div[18]/p[16]", "#XFUNC-C/div[18]/p[18]", "#XFUNC-C/div[18]/p[19]", "#XFUNC-C/div[18]/p[1]", "#XFUNC-C/div[18]/p[20]", "#XFUNC-C/div[18]/p[3]", "#XFUNC-C/div[18]/p[4]", "#XFUNC-C/div[18]/p[6]", "#XFUNC-C/div[18]/p[7]", "#XFUNC-C/div[19]/p[10]", "#XFUNC-C/div[19]/p[1]", "#XFUNC-C/div[19]/p[2]", "#XFUNC-C/div[19]/p[4]", "#XFUNC-C/div[19]/p[6]", "#XFUNC-C/div[19]/p[7]", "#XFUNC-C/div[19]/p[8]", "#XFUNC-C/div[19]/p[9]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[12]", "#XFUNC-C/div[1]/dl[0]/dt[13]", "#XFUNC-C/div[1]/dl[0]/dt[14]", "#XFUNC-C/div[1]/dl[0]/dt[15]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[20]/p[2]", "#XFUNC-C/div[20]/p[4]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[12]", "#XFUNC-C/div[5]/p[14]", "#XFUNC-C/div[5]/p[16]", "#XFUNC-C/div[5]/p[18]", "#XFUNC-C/div[5]/p[19]", "#XFUNC-C/div[5]/p[22]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[10]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[17]", "#XFUNC-C/div[7]/p[18]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[20]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[7]", "#XFUNC-C/div[7]/p[8]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/summary": "dynamically-loaded C functions", "/category": "Native function languages", "/versions/20/description/0": "dynamically-loaded C functions", "/versions/20/facts/0/label": "Kind", "/versions/20/facts/0/value": "Native function language", "/versions/20/facts/1/label": "Trusted", "/versions/20/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "67a086fec10f7b84ed256f363644df8de3001be1b8f5c5d5a8a8489686669c64"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}}}, "snapshot": {"facts": [{"label": "\u79cd\u7c7b", "value": "\u539f\u751f\u51fd\u6570\u8bed\u8a00"}, {"label": "\u53ef\u4fe1", "value": "f"}, {"label": "\u6821\u9a8c\u51fd\u6570", "value": "fmgr_c_validator"}], "tables": [], "aliases": [], "catalog": {"oid": "13", "descr": "dynamically-loaded C functions", "lanacl": "_null_", "lanispl": "f", "lanname": "c", "lanowner": "POSTGRES", "laninline": "0", "oid_symbol": "ClanguageId", "lanpltrusted": "f", "lanvalidator": "fmgr_c_validator", "lanplcallfoid": "0"}, "related": [], "release": {"ref": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "catalog_fingerprint": "65c93d6048ef30e61023a84f9680fa6a92b1c383b7eb226741170077eb078502"}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "label": "Matching PostgreSQL source archive", "sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://pg.center/docs/18/xfunc-c.html", "path": "xfunc-c.html", "label": "PostgreSQL 18 English manual", "sha256": "d60592edc11f3240b19cecee91523a9a31f1caf68809fa7a39376360d957d68b", "language": "en", "original_url": "/docs/18/xfunc-c.html"}], "sections": [], "signature": "", "attributes": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "description": ["\u52a8\u6001\u52a0\u8f7d\u7684 C \u51fd\u6570"], "manual_html": "<div class=\"sect1\" id=\"XFUNC-C\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h2 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h2 class=\"title\" style=\"clear: both\">36.10.\u00a0C \u8bed\u8a00\u51fd\u6570 </h2>\n</div>\n</div>\n</h2>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528\u6237\u5b9a\u4e49\u7684\u51fd\u6570\u53ef\u4ee5\u7528 C \u7f16\u5199\uff08\u6216\u8005\u53ef\u4ee5\u4e0e C \u517c\u5bb9\u7684\u8bed\u8a00\uff0c\u4f8b\u5982 C++\uff09\u3002\u8fd9\u7c7b\u51fd\u6570\u88ab\u7f16\u8bd1\u6210\u52a8\u6001\u8f7d\u5165\u5bf9\u8c61\uff08\u4e5f\u88ab\u79f0\u4e3a\u5171\u4eab\u5e93\uff09\u5e76\u4e14\u7531\u670d\u52a1\u5668\u5728\u9700\u8981\u65f6\u8f7d\u5165\u3002\u52a8\u6001\u8f7d\u5165\u662f\u628a<span class=\"quote\">\u201c<span class=\"quote\">C\u8bed\u8a00</span>\u201d</span>\u51fd\u6570\u548c<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u90e8</span>\u201d</span>\u51fd\u6570\u533a\u5206\u5f00\u7684\u7279\u6027 \u2014 \u4e24\u8005\u771f\u6b63\u7684\u7f16\u7801\u4e60\u60ef\u5b9e\u9645\u4e0a\u662f\u4e00\u6837\u7684\uff08\u56e0\u6b64\uff0c\u6807\u51c6\u5185\u90e8\u51fd\u6570\u5e93\u4e3a\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u7f16\u7801\u793a\u4f8b\uff09\u3002</p>\n<p lang=\"zh\">\u76ee\u524d C \u51fd\u6570\u4ec5\u4f7f\u7528\u4e00\u79cd\u8c03\u7528\u7ea6\u5b9a\uff08\u201c\u7248\u672c 1\u201d\uff09\u3002\u901a\u8fc7\u4e3a\u51fd\u6570\u7f16\u5199 PG_FUNCTION_INFO_V1() \u5b8f\u8c03\u7528\u6765\u8868\u660e\u652f\u6301\u6b64\u8c03\u7528\u7ea6\u5b9a\uff0c\u793a\u4f8b\u5982\u4e0b\u3002</p>\n<div class=\"sect2\" id=\"XFUNC-C-DYNLOAD\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-DYNLOAD\">36.10.1. \u52a8\u6001\u8f7d\u5165</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\u7b2c\u4e00\u6b21\u8c03\u7528\u4e00\u4e2a\u7279\u5b9a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4e2d\u7684\u7528\u6237\u5b9a\u4e49\u51fd\u6570\u65f6\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u4f1a\u628a\u90a3\u4e2a\u76ee\u6807\u6587\u4ef6\u8f7d\u5165\u5230\u5185\u5b58\u4ee5\u4fbf\u8be5\u51fd\u6570\u88ab\u8c03\u7528\u3002\u56e0\u6b64\u7528\u6237\u5b9a\u4e49\u7684 C \u51fd\u6570\u7684<code class=\"command\">CREATE FUNCTION</code>\u5fc5\u987b\u4e3a\u8be5\u51fd\u6570\u6307\u5b9a\u4e24\u5757\u4fe1\u606f\uff1a\u53ef\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u8981\u5728\u8be5\u76ee\u6807\u6587\u4ef6\u4e2d\u8c03\u7528\u7684\u7279\u5b9a\u51fd\u6570\u7684 C \u540d\u79f0\uff08\u94fe\u63a5\u7b26\u53f7\uff09\u3002\u5982\u679c\u6ca1\u6709\u663e\u5f0f\u6307\u5b9a C \u540d\u79f0\uff0c\u5219\u5b83\u88ab\u5047\u5b9a\u4e3a\u548c SQL \u51fd\u6570\u540d\u76f8\u540c\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u7b97\u6cd5\u88ab\u7528\u6765\u57fa\u4e8e<code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u540d\u79f0\u6765\u5b9a\u4f4d\u5171\u4eab\u76ee\u6807\u6587\u4ef6\uff1a</p>\n<div class=\"orderedlist\">\n<ol class=\"orderedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u540d\u79f0\u662f\u4e00\u4e2a\u7edd\u5bf9\u8def\u5f84\uff0c\u5219\u8f7d\u5165\u7ed9\u5b9a\u7684\u6587\u4ef6\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4ee5\u5b57\u7b26\u4e32<code class=\"literal\">$libdir</code>\u5f00\u59cb\uff0c\u90a3\u4e48\u8fd9\u4e00\u90e8\u5206\u4f1a\u88ab <span class=\"productname\">PostgreSQL</span>\u5305\u7684\u5e93\u76ee\u5f55\u540d\uff08\u5728\u7f16\u8bd1\u65f6\u786e\u5b9a\uff09\u66ff\u6362\u3002 <a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.2.1.3\" name=\"id-1.8.3.13.5.4.2.2.1.3\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5982\u679c\u8be5\u540d\u79f0\u4e0d\u5305\u542b\u76ee\u5f55\u90e8\u5206\uff0c\u4f1a\u5728\u914d\u7f6e\u53d8\u91cf<a class=\"xref\" href=\"/docs/18/runtime-config-client.html#GUC-DYNAMIC-LIBRARY-PATH\">dynamic_library_path</a>\u6307\u5b9a\u7684\u8def\u5f84\u4e2d\u641c\u7d22\u8be5\u6587\u4ef6\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.5.4.2.3.1.2\" name=\"id-1.8.3.13.5.4.2.3.1.2\"></a></p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5426\u5219\uff08\u5728\u8be5\u8def\u5f84\u4e2d\u6ca1\u627e\u5230\u8be5\u6587\u4ef6\uff0c\u6216\u8005\u5b83\u5305\u542b\u4e00\u4e2a\u975e\u7edd\u5bf9\u76ee\u5f55\uff09\uff0c\u52a8\u6001\u8f7d\u5165\u5668\u5c06\u5c1d\u8bd5\u63a5\u53d7\u7ed9\u5b9a\u7684\u540d\u79f0\uff0c\u8fd9\u5f88\u53ef\u80fd\u4f1a\u5931\u8d25\uff08\u4f9d\u8d56\u5f53\u524d\u5de5\u4f5c\u76ee\u5f55\u662f\u4e0d\u53ef\u9760\u7684\uff09\u3002</p>\n</li>\n</ol>\n</div>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e2a\u5e8f\u5217\u4e0d\u8d77\u4f5c\u7528\uff0c\u4f1a\u628a\u5e73\u53f0\u76f8\u5173\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u540d\u6269\u5c55\uff08\u901a\u5e38\u662f <code class=\"filename\">.so</code>\uff09\u8ffd\u52a0\u5230\u7ed9\u5b9a\u7684\u540d\u79f0\u5e76\u4e14\u518d\u6b21\u5c1d\u8bd5\u4e0a\u8ff0\u7684\u8fc7\u7a0b\u3002\u5982\u679c\u8fd8\u662f\u5931\u8d25\uff0c\u5219\u8f7d\u5165\u5931\u8d25\u3002</p>\n<p lang=\"zh\">\u5efa\u8bae\u901a\u8fc7\u76f8\u5bf9\u4e8e <code class=\"literal\">$libdir</code> \u7684\u8def\u5f84\uff0c\u6216\u8005\u901a\u8fc7\u52a8\u6001\u5e93\u8def\u5f84\u6765\u5b9a\u4f4d\u5171\u4eab\u5e93\u3002\u8fd9\u6837\u4e00\u6765\uff0c\u5982\u679c\u65b0\u5b89\u88c5\u4f4d\u4e8e\u4e0d\u540c\u7684\u4f4d\u7f6e\uff0c\u7248\u672c\u5347\u7ea7\u4f1a\u66f4\u7b80\u5355\u3002<code class=\"literal\">$libdir</code> \u5b9e\u9645\u4ee3\u8868\u7684\u76ee\u5f55\u53ef\u4ee5\u901a\u8fc7\u547d\u4ee4 <code class=\"literal\">pg_config --pkglibdir</code> \u67e5\u51fa\u3002</p>\n<p lang=\"zh\">\u7528\u4e8e\u8fd0\u884c<span class=\"productname\">PostgreSQL</span>\u670d\u52a1\u5668\u7684\u7528\u6237 ID \u5fc5\u987b\u80fd\u591f\u904d\u5386\u901a\u5f80\u8981\u8f7d\u5165\u6587\u4ef6\u7684\u8def\u5f84\u3002\u5e38\u89c1\u7684\u9519\u8bef\u662f\u628a\u6587\u4ef6\u6216\u66f4\u9ad8\u5c42\u7684\u76ee\u5f55\u53d8\u5f97\u5bf9<span class=\"systemitem\">postgres</span>\u7528\u6237\u4e0d\u53ef\u8bfb\u6216\u8005\u4e0d\u53ef\u6267\u884c\u3002</p>\n<p lang=\"zh\">\u5728\u4efb\u4f55\u60c5\u51b5\u4e0b\uff0c<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u7ed9\u5b9a\u7684\u6587\u4ef6\u540d\u4f1a\u88ab\u539f\u5c01\u4e0d\u52a8\u5730\u8bb0\u5f55\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\uff0c\u8fd9\u6837\u5982\u679c\u9700\u8981\u518d\u6b21\u8f7d\u5165\u8be5\u6587\u4ef6\u5219\u4f1a\u5e94\u7528\u540c\u6837\u7684\u8fc7\u7a0b\u3002</p>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span>\u4e0d\u4f1a\u81ea\u52a8\u7f16\u8bd1 C \u51fd\u6570\u3002\u5728\u4ece<code class=\"command\">CREATE FUNCTION</code>\u547d\u4ee4\u4e2d\u5f15\u7528\u76ee\u6807\u6587\u4ef6\u4e4b\u524d\uff0c\u5b83\u5fc5\u987b\u5148\u88ab\u7f16\u8bd1\u597d\u3002\u66f4\u591a\u4fe1\u606f\u8bf7\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</div>\n<p lang=\"zh\">\u4e3a\u786e\u4fdd\u52a8\u6001\u88c5\u8f7d\u7684\u76ee\u6807\u6587\u4ef6\u4e0d\u4f1a\u88ab\u52a0\u8f7d\u5230\u4e0d\u517c\u5bb9\u7684\u670d\u52a1\u5668\u4e2d\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u68c0\u67e5\u8be5\u6587\u4ef6\u662f\u5426\u5305\u542b\u5185\u5bb9\u6b63\u786e\u7684<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002\u8fd9\u6837\u670d\u52a1\u5668\u5c31\u80fd\u68c0\u6d4b\u51fa\u660e\u663e\u7684\u4e0d\u517c\u5bb9\u60c5\u51b5\uff0c\u4f8b\u5982\u4ee3\u7801\u662f\u9488\u5bf9\u53e6\u4e00\u4e2a <span class=\"productname\">PostgreSQL</span> \u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u3002\u8981\u52a0\u5165\u9b54\u6570\u5757\uff0c\u8bf7\u5728\u6a21\u5757\u67d0\u4e00\u4e2a\uff08\u4e14\u53ea\u80fd\u4e00\u4e2a\uff09\u6e90\u6587\u4ef6\u4e2d\uff0c\u5728\u5305\u542b\u5934\u6587\u4ef6 <code class=\"filename\">fmgr.h</code> \u4e4b\u540e\u5199\u5165\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC;\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC_EXT(<em class=\"replaceable\"><code>parameters</code></em>);\n</pre>\n<p lang=\"zh\"><code class=\"literal\">PG_MODULE_MAGIC_EXT</code> \u8fd9\u79cd\u5f62\u5f0f\u5141\u8bb8\u4e3a\u6a21\u5757\u6307\u5b9a\u9644\u52a0\u4fe1\u606f\uff1b\u76ee\u524d\u53ef\u4ee5\u6dfb\u52a0\u540d\u79f0\u548c/\u6216\u7248\u672c\u5b57\u7b26\u4e32\u3002\uff08\u5c06\u6765\u53ef\u80fd\u5141\u8bb8\u66f4\u591a\u5b57\u6bb5\u3002\uff09\u53ef\u4ee5\u5199\u6210\u8fd9\u6837\uff1a</p>\n<pre class=\"programlisting\">PG_MODULE_MAGIC_EXT(\n    .name = \"my_module_name\",\n    .version = \"1.2.3\"\n);\n</pre>\n<p lang=\"zh\">\u4e4b\u540e\uff0c\u540d\u79f0\u548c\u7248\u672c\u53ef\u4ee5\u901a\u8fc7 <code class=\"function\">pg_get_loaded_modules()</code> \u51fd\u6570\u67e5\u770b\u3002\u7248\u672c\u5b57\u7b26\u4e32\u7684\u5177\u4f53\u542b\u4e49\u4e0d\u53d7 <span class=\"productname\">PostgreSQL</span> \u9650\u5236\uff0c\u4f46\u5efa\u8bae\u91c7\u7528\u8bed\u4e49\u5316\u7248\u672c\u89c4\u5219\u3002</p>\n<p lang=\"zh\">\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u4e4b\u540e\uff0c\u52a8\u6001\u8f7d\u5165\u76ee\u6807\u6587\u4ef6\u4f1a\u4fdd\u7559\u5728\u5185\u5b58\u4e2d\u3002\u5728\u540c\u4e00\u4e2a\u4f1a\u8bdd\u4e2d\uff0c\u540e\u7eed\u5bf9\u8be5\u6587\u4ef6\u4e2d\u51fd\u6570\u7684\u8c03\u7528\u53ea\u9700\u4ed8\u51fa\u4e00\u6b21\u5f88\u5c0f\u7684\u7b26\u53f7\u8868\u67e5\u627e\u5f00\u9500\u3002\u5982\u679c\u9700\u8981\u5f3a\u5236\u91cd\u65b0\u8f7d\u5165\u4e00\u4e2a\u76ee\u6807\u6587\u4ef6\uff08\u4f8b\u5982\u5728\u91cd\u65b0\u7f16\u8bd1\u4e4b\u540e\uff09\uff0c\u5c31\u9700\u8981\u5f00\u542f\u4e00\u4e2a\u65b0\u7684\u4f1a\u8bdd\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u53ef\u4ee5\u5305\u542b\u4e00\u4e2a\u521d\u59cb\u5316\u51fd\u6570\u3002\u5982\u679c\u6587\u4ef6\u5305\u542b\u4e00\u4e2a\u540d\u4e3a <code class=\"function\">_PG_init</code>\u7684\u51fd\u6570\uff0c\u90a3\u4e2a\u51fd\u6570\u5c06\u5728\u52a0\u8f7d\u6587\u4ef6\u540e\u7acb\u5373\u88ab\u8c03\u7528\u3002\u8be5\u51fd\u6570\u4e0d\u63a5\u6536\u4efb\u4f55\u53c2\u6570\uff0c\u5e94\u8be5\u8fd4\u56devoid\u3002\u76ee\u524d\u6ca1\u6709\u529e\u6cd5\u5378\u8f7d\u4e00\u4e2a\u52a8\u6001\u52a0\u8f7d\u7684\u6587\u4ef6\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-BASETYPE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-BASETYPE\">36.10.2. C \u8bed\u8a00\u51fd\u6570\u4e2d\u7684\u57fa\u7840\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4e86\u89e3\u5982\u4f55\u7f16\u5199 C \u8bed\u8a00\u51fd\u6570\uff0c\u4f60\u9700\u8981\u4e86\u89e3 <span class=\"productname\">PostgreSQL</span>\u5982\u4f55\u5728\u5185\u90e8\u8868\u8fbe\u57fa\u7840\u7c7b\u578b\u4ee5\u53ca\u5982\u4f55\u5c06\u5b83\u4eec\u4f20\u5165\u51fd\u6570\u548c\u4ece\u51fd\u6570\u4f20\u51fa\u3002\u5728\u5185\u90e8\uff0c<span class=\"productname\">PostgreSQL</span>\u628a\u57fa\u7840\u7c7b\u578b\u89c6\u4e3a\u4e00\u5757<span class=\"quote\">\u201c<span class=\"quote\">\u5185\u5b58\u6570\u636e\u5757</span>\u201d</span>\u3002\u4f60\u4e3a\u8be5\u7c7b\u578b\u5b9a\u4e49\u7684\u7528\u6237\u81ea\u5b9a\u4e49\u51fd\u6570\uff0c\u51b3\u5b9a\u4e86 <span class=\"productname\">PostgreSQL</span> \u5982\u4f55\u64cd\u4f5c\u5b83\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c<span class=\"productname\">PostgreSQL</span> \u53ea\u8d1f\u8d23\u628a\u6570\u636e\u5b58\u5230\u78c1\u76d8\u3001\u518d\u4ece\u78c1\u76d8\u53d6\u56de\uff0c\u800c\u6570\u636e\u7684\u8f93\u5165\u3001\u5904\u7406\u548c\u8f93\u51fa\u5219\u4f9d\u8d56\u4f60\u5b9a\u4e49\u7684\u8fd9\u4e9b\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u57fa\u7840\u7c7b\u578b\u53ef\u4ee5\u6709\u4e09\u79cd\u5185\u90e8\u683c\u5f0f\u4e4b\u4e00\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u503c\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u5b9a\u957f</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f20\u5f15\u7528\uff0c\u53d8\u957f</p>\n</li>\n</ul>\n</div>\n<p lang=\"zh\">\u4f20\u503c\u7c7b\u578b\u5728\u957f\u5ea6\u4e0a\u53ea\u80fd\u662f 1\u30012 \u6216 4 \u5b57\u8282\uff08\u5982\u679c\u4f60\u7684\u673a\u5668\u4e0a <code class=\"literal\">sizeof(Datum)</code>\u662f 8\uff0c\u5219\u8fd8\u6709 8 \u5b57\u8282\uff09\u3002\u4f60\u5e94\u5f53\u5c0f\u5fc3\u5730\u5b9a\u4e49\u4f60\u7684\u7c7b\u578b\u4ee5\u4fbf\u5b83\u4eec\u5728\u6240\u6709\u7684\u67b6\u6784\u4e0a\u90fd\u662f\u76f8\u540c\u7684\u5c3a\u5bf8\uff08\u5b57\u8282\uff09\u3002\u4f8b\u5982\uff0c<code class=\"literal\">long</code>\u7c7b\u578b\u5f88\u5371\u9669\uff0c\u56e0\u4e3a\u5b83\u5728\u67d0\u4e9b\u673a\u5668\u4e0a\u662f 4 \u5b57\u8282\u4f46\u5728\u53e6\u5916\u4e00\u4e9b\u673a\u5668\u4e0a\u662f 8 \u5b57\u8282\uff0c\u800c<code class=\"type\">int</code>\u7c7b\u578b\u5728\u5927\u90e8\u5206 Unix \u673a\u5668\u4e0a\u90fd\u662f 4 \u5b57\u8282\u3002\u5728 Unix \u673a\u5668\u4e0a<code class=\"type\">int4</code>\u7c7b\u578b\u7684\u4e00\u79cd\u5408\u7406\u5b9e\u73b0\u53ef\u80fd\u662f\uff1a</p>\n<pre class=\"programlisting\">/* 4-byte integer, passed by value */\ntypedef int int4;\n</pre>\n<p lang=\"zh\">\uff08\u5b9e\u9645\u7684 PostgreSQL C \u4ee3\u7801\u4f1a\u628a\u8fd9\u79cd\u7c7b\u578b\u79f0\u4e3a<code class=\"type\">int32</code>\uff0c\u56e0\u4e3a C \u4e2d\u7684\u4e60\u60ef\u662f<code class=\"type\">int<em class=\"replaceable\"><code>XX</code></em></code> \u8868\u793a<em class=\"replaceable\"><code>XX</code></em> <span class=\"emphasis\"><em>\u4f4d</em></span>\u3002\u6ce8\u610f\u56e0\u6b64\u8fd8\u6709\u5c3a\u5bf8\u4e3a 1 \u5b57\u8282\u7684 C \u7c7b\u578b<code class=\"type\">int8</code>\u3002SQL \u7c7b\u578b <code class=\"type\">int8</code>\u5728 C \u4e2d\u88ab\u79f0\u4e3a<code class=\"type\">int64</code>\u3002\u53e6\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\uff09\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u65b9\u9762\uff0c\u4efb\u610f\u5c3a\u5bf8\u7684\u5b9a\u957f\u7c7b\u578b\u90fd\u53ef\u4ee5\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u3002\u4f8b\u5982\uff0c\u8fd9\u91cc\u6709\u4e00\u79cd <span class=\"productname\">PostgreSQL</span>\u7c7b\u578b\u7684\u5b9e\u73b0\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">/* 16-byte structure, passed by reference */\ntypedef struct\n{\n    double  x, y;\n} Point;\n</pre>\n<p lang=\"zh\">\u5728<span class=\"productname\">PostgreSQL</span>\u51fd\u6570\u4e2d\u4f20\u8fdb\u6216\u4f20\u51fa\u8fd9\u79cd\u7c7b\u578b\u65f6\uff0c\u53ea\u80fd\u4f7f\u7528\u6307\u5411\u8fd9\u79cd\u7c7b\u578b\u7684\u6307\u9488\u3002\u8981\u8fd4\u56de\u8fd9\u6837\u4e00\u79cd\u7c7b\u578b\u7684\u503c\uff0c\u7528 <code class=\"literal\">palloc</code>\u5206\u914d\u6b63\u786e\u7684\u5185\u5b58\u91cf\uff0c\u7136\u540e\u586b\u5145\u5206\u914d\u597d\u7684\u5185\u5b58\uff0c\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u6307\u5411\u8be5\u5185\u5b58\u7684\u6307\u9488\uff08\u8fd8\u6709\uff0c\u5982\u679c\u53ea\u60f3\u8fd4\u56de\u4e0e\u5177\u6709\u76f8\u540c\u6570\u636e\u7c7b\u578b\u7684\u4e00\u4e2a\u8f93\u5165\u53c2\u6570\u76f8\u540c\u7684\u503c\uff0c\u53ef\u4ee5\u8df3\u8fc7\u989d\u5916\u7684<code class=\"literal\">palloc</code>\u5e76\u4e14\u8fd4\u56de\u6307\u5411\u8be5\u8f93\u5165\u503c\u7684\u6307\u9488\uff09\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u4e5f\u4ee5\u5f15\u7528\u7684\u65b9\u5f0f\u4f20\u9012\u3002\u6240\u6709\u53d8\u957f\u7c7b\u578b\u5fc5\u987b\u7528\u4e00\u4e2a\u6b63\u597d 4 \u5b57\u8282\u7684\u4e0d\u900f\u660e\u957f\u5ea6\u5b57\u6bb5\u5f00\u59cb\uff0c\u8be5\u5b57\u6bb5\u4f1a\u7531<code class=\"symbol\">SET_VARSIZE</code> \u8bbe\u7f6e\uff0c\u7edd\u4e0d\u8981\u76f4\u63a5\u8bbe\u7f6e\u8be5\u5b57\u6bb5\uff01\u6240\u6709\u8981\u88ab\u5b58\u50a8\u5728\u8be5\u7c7b\u578b\u4e2d\u7684\u6570\u636e\u5fc5\u987b\u5728\u5185\u5b58\u4e2d\u63a5\u7740\u8be5\u957f\u5ea6\u5b57\u6bb5\u7684\u540e\u9762\u5b58\u50a8\u3002\u957f\u5ea6\u5b57\u6bb5\u5305\u542b\u8be5\u7ed3\u6784\u4f53\u7684\u603b\u957f\u5ea6\uff0c\u4e5f\u5c31\u662f\u5305\u62ec\u957f\u5ea6\u5b57\u6bb5\u672c\u8eab\u7684\u5c3a\u5bf8\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u4e2a\u91cd\u70b9\u662f\u8981\u907f\u514d\u5728\u6570\u636e\u7c7b\u578b\u503c\u4e2d\u7559\u4e0b\u672a\u88ab\u521d\u59cb\u5316\u7684\u4f4d\u3002\u4f8b\u5982\uff0c\u8981\u6ce8\u610f\u628a\u53ef\u80fd\u5b58\u5728\u4e8e\u7ed3\u6784\u4f53\u4e2d\u7684\u4efb\u4f55\u5bf9\u9f50\u586b\u5145\u5b57\u8282\u7f6e\u96f6\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u4f60\u7684\u6570\u636e\u7c7b\u578b\u7684\u903b\u8f91\u7b49\u4ef7\u5e38\u91cf\u53ef\u80fd\u4f1a\u88ab\u89c4\u5212\u5668\u8ba4\u4e3a\u662f\u4e0d\u7b49\u7684\uff0c\u8fdb\u800c\u5bfc\u81f4\u4f4e\u6548\u7684\uff08\u4e0d\u8fc7\u8fd8\u662f\u6b63\u786e\u7684\uff09\u8ba1\u5212\u3002</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\"><span class=\"emphasis\"><em>\u7edd\u4e0d\u8981</em></span>\u4fee\u6539\u901a\u8fc7\u5f15\u7528\u4f20\u9012\u7684\u8f93\u5165\u503c\u7684\u5185\u5bb9\u3002\u5982\u679c\u8fd9\u6837\u505a\u5f88\u53ef\u80fd\u4f1a\u7834\u574f\u78c1\u76d8\u4e0a\u7684\u6570\u636e\uff0c\u56e0\u4e3a\u7ed9\u51fa\u7684\u6307\u9488\u53ef\u80fd\u76f4\u63a5\u6307\u5411\u4e00\u4e2a\u78c1\u76d8\u7f13\u51b2\u533a\u3002\u8fd9\u6761\u89c4\u5219\u552f\u4e00\u7684\u4f8b\u5916\u5728<a class=\"xref\" href=\"/docs/18/xaggr.html\" title=\"36.12.\u00a0\u7528\u6237\u5b9a\u4e49\u7684\u805a\u5408\">\u7b2c\u00a036.12\u00a0\u8282</a>\u4e2d\u6709\u89e3\u91ca\u3002</p>\n</div>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u6211\u4eec\u53ef\u4ee5\u8fd9\u6837\u5b9a\u4e49\u7c7b\u578b<code class=\"type\">text</code>\uff1a</p>\n<pre class=\"programlisting\">typedef struct {\n    int32 length;\n    char data[FLEXIBLE_ARRAY_MEMBER];\n} text;\n</pre>\n<p lang=\"zh\"><code class=\"literal\">[FLEXIBLE_ARRAY_MEMBER]</code>\u8bb0\u53f7\u8868\u793a\u6570\u636e\u90e8\u5206\u7684\u5b9e\u9645\u957f\u5ea6\u4e0d\u7531\u8be5\u58f0\u660e\u6307\u5b9a\u3002</p>\n<p lang=\"zh\">\u5728\u64cd\u4f5c\u53d8\u957f\u7c7b\u578b\u65f6\uff0c\u6211\u4eec\u5fc5\u987b\u5c0f\u5fc3\u5206\u914d\u6b63\u786e\u6570\u91cf\u7684\u5185\u5b58\uff0c\u5e76\u6b63\u786e\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\u3002\u4f8b\u5982\uff0c\u5982\u679c\u6211\u4eec\u60f3\u5728\u4e00\u4e2a<code class=\"structname\">text</code>\u7ed3\u6784\u4f53\u4e2d\u5b58\u50a8 40 \u5b57\u8282\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528\u8fd9\u6837\u7684\u4ee3\u7801\u7247\u6bb5\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n...\nchar buffer[40]; /* our source data */\n...\ntext *destination = (text *) palloc(VARHDRSZ + 40);\nSET_VARSIZE(destination, VARHDRSZ + 40);\nmemcpy(destination-&gt;data, buffer, 40);\n...\n\n</pre>\n<p lang=\"zh\"><code class=\"literal\">VARHDRSZ</code>\u548c<code class=\"literal\">sizeof(int32)</code>\u4e00\u6837\uff0c\u4f46\u662f\u7528\u5b8f<code class=\"literal\">VARHDRSZ</code>\u6765\u5f15\u7528\u53d8\u957f\u7c7b\u578b\u7684\u989d\u5916\u5f00\u9500\u7684\u5c3a\u5bf8\u88ab\u8ba4\u4e3a\u662f\u6bd4\u8f83\u597d\u7684\u98ce\u683c\u3002\u8fd8\u6709\uff0c<span class=\"emphasis\"><em>\u5fc5\u987b</em></span>\u4f7f\u7528<code class=\"literal\">SET_VARSIZE</code>\u5b8f\u6765\u8bbe\u7f6e\u957f\u5ea6\u5b57\u6bb5\uff0c\u800c\u4e0d\u662f\u7528\u7b80\u5355\u7684\u8d4b\u503c\u6765\u8bbe\u7f6e\u3002</p>\n<p lang=\"zh\"><a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-TYPE-TABLE\" title=\"\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b\">\u8868\u00a036.2</a>\u5c55\u793a\u4e86 <span class=\"productname\">PostgreSQL</span> \u4e2d\u8bb8\u591a\u5185\u7f6e SQL \u6570\u636e\u7c7b\u578b\u6240\u5bf9\u5e94\u7684 C \u7c7b\u578b\u3002<span class=\"quote\">\u201c<span class=\"quote\">\u5b9a\u4e49\u6587\u4ef6</span>\u201d</span>\u5217\u7ed9\u51fa\u4e86\u9700\u8981\u5305\u542b\u7684\u5934\u6587\u4ef6\uff0c\u4ee5\u83b7\u53d6\u7c7b\u578b\u5b9a\u4e49\u3002\uff08\u5b9e\u9645\u7684\u5b9a\u4e49\u53ef\u80fd\u4f4d\u4e8e\u6240\u5217\u6587\u4ef6\u5305\u542b\u7684\u5176\u4ed6\u6587\u4ef6\u4e2d\u3002\u5efa\u8bae\u7528\u6237\u575a\u6301\u4f7f\u7528\u5df2\u5b9a\u4e49\u7684\u63a5\u53e3\u3002\uff09\u8bf7\u6ce8\u610f\uff0c\u5728\u670d\u52a1\u5668\u4ee3\u7801\u7684\u4efb\u4f55\u6e90\u6587\u4ef6\u4e2d\uff0c\u90fd\u5e94\u8be5\u59cb\u7ec8\u9996\u5148\u5305\u542b<code class=\"filename\">postgres.h</code>\uff0c\u56e0\u4e3a\u5b83\u58f0\u660e\u4e86\u5f88\u591a\u4f60\u53cd\u6b63\u90fd\u4f1a\u7528\u5230\u7684\u5185\u5bb9\uff0c\u800c\u4e14\u5148\u5305\u542b\u5176\u4ed6\u5934\u6587\u4ef6\u53ef\u80fd\u4f1a\u5e26\u6765\u53ef\u79fb\u690d\u6027\u95ee\u9898\u3002</p>\n<div class=\"table\" id=\"XFUNC-C-TYPE-TABLE\">\n<p class=\"title\" lang=\"zh\"><strong>\u8868\u00a036.2.\u00a0\u5185\u7f6e SQL \u7c7b\u578b\u7b49\u6548\u7684 C \u7c7b\u578b</strong></p>\n<div class=\"table-contents\">\n<table class=\"table\">\n<thead>\n<tr>\n<th lang=\"zh\">SQL \u7c7b\u578b</th>\n<th lang=\"zh\">C \u7c7b\u578b</th>\n<th lang=\"zh\">\u5b9a\u4e49\u6587\u4ef6</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td><code class=\"type\">boolean</code></td>\n<td><code class=\"type\">bool</code></td>\n<td lang=\"zh\"><code class=\"filename\">postgres.h</code>\uff08\u53ef\u80fd\u662f\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">box</code></td>\n<td><code class=\"type\">BOX*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">bytea</code></td>\n<td><code class=\"type\">bytea*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">\"char\"</code></td>\n<td><code class=\"type\">char</code></td>\n<td lang=\"zh\">\uff08\u7f16\u8bd1\u5668\u5185\u7f6e\uff09</td>\n</tr>\n<tr>\n<td><code class=\"type\">character</code></td>\n<td><code class=\"type\">BpChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">cid</code></td>\n<td><code class=\"type\">CommandId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">date</code></td>\n<td><code class=\"type\">DateADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float4</code> (<code class=\"type\">real</code>)</td>\n<td><code class=\"type\">float4</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">float8</code> (<code class=\"type\">double precision</code>)</td>\n<td><code class=\"type\">float8</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int2</code> (<code class=\"type\">smallint</code>)</td>\n<td><code class=\"type\">int16</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int4</code> (<code class=\"type\">integer</code>)</td>\n<td><code class=\"type\">int32</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">int8</code> (<code class=\"type\">bigint</code>)</td>\n<td><code class=\"type\">int64</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">interval</code></td>\n<td><code class=\"type\">Interval*</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">lseg</code></td>\n<td><code class=\"type\">LSEG*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">name</code></td>\n<td><code class=\"type\">Name</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">numeric</code></td>\n<td lang=\"zh\">\u6570\u503c</td>\n<td><code class=\"filename\">utils/numeric.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oid</code></td>\n<td><code class=\"type\">Oid</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">oidvector</code></td>\n<td><code class=\"type\">oidvector*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">path</code></td>\n<td><code class=\"type\">PATH*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">point</code></td>\n<td><code class=\"type\">POINT*</code></td>\n<td><code class=\"filename\">utils/geo_decls.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">regproc</code></td>\n<td><code class=\"type\">RegProcedure</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td lang=\"zh\">\u6587\u672c</td>\n<td><code class=\"type\">text*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">tid</code></td>\n<td><code class=\"type\">ItemPointer</code></td>\n<td><code class=\"filename\">storage/itemptr.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time</code></td>\n<td><code class=\"type\">TimeADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">time with time zone</code></td>\n<td><code class=\"type\">TimeTzADT</code></td>\n<td><code class=\"filename\">utils/date.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp</code></td>\n<td><code class=\"type\">Timestamp</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">timestamp with time zone</code></td>\n<td><code class=\"type\">TimestampTz</code></td>\n<td><code class=\"filename\">datatype/timestamp.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">varchar</code></td>\n<td><code class=\"type\">VarChar*</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n<tr>\n<td><code class=\"type\">xid</code></td>\n<td><code class=\"type\">TransactionId</code></td>\n<td><code class=\"filename\">postgres.h</code></td>\n</tr>\n</tbody>\n</table>\n</div>\n</div><br class=\"table-break\"/>\n<p lang=\"zh\">\u4e86\u89e3\u4e86\u57fa\u7840\u7c7b\u578b\u6240\u6709\u53ef\u80fd\u7684\u7ed3\u6784\u540e\uff0c\u5c31\u53ef\u4ee5\u770b\u4e00\u4e9b\u5b9e\u9645\u51fd\u6570\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-V1-CALL-CONV\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-V1-CALL-CONV\">36.10.3. \u7248\u672c 1 \u7684\u8c03\u7528\u7ea6\u5b9a</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7248\u672c-1 \u7684\u8c03\u7528\u7ea6\u5b9a\u4f9d\u8d56\u4e8e\u5b8f\u6765\u5c4f\u853d\u4f20\u9012\u53c2\u6570\u548c\u7ed3\u679c\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u7248\u672c-1 \u51fd\u6570\u7684 C \u58f0\u660e\u603b\u662f\uff1a</p>\n<pre class=\"programlisting\">Datum funcname(PG_FUNCTION_ARGS)\n</pre>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5b8f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(funcname);\n</pre>\n<p lang=\"zh\">\u5fc5\u987b\u51fa\u73b0\u5728\u540c\u4e00\u4e2a\u6e90\u6587\u4ef6\u4e2d\uff08\u6309\u60ef\u4f8b\u4f1a\u6b63\u597d\u5199\u5728\u8be5\u51fd\u6570\u672c\u8eab\u4e4b\u524d\uff09\u3002\u8fd9\u79cd\u5b8f\u8c03\u7528\u4e0d\u662f<code class=\"literal\">internal</code>\u8bed\u8a00\u51fd\u6570\u6240\u9700\u8981\u7684\uff0c\u56e0\u4e3a <span class=\"productname\">PostgreSQL</span>\u4f1a\u5047\u5b9a\u6240\u6709\u5185\u90e8\u51fd\u6570\u90fd\u4f7f\u7528\u7248\u672c-1 \u8c03\u7528\u7ea6\u5b9a\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u52a8\u6001\u8f7d\u5165\u51fd\u6570\u662f\u5fc5\u9700\u7684\u3002</p>\n<p lang=\"zh\">\u5728\u7248\u672c-1 \u51fd\u6570\u4e2d\uff0c\u6bcf\u4e00\u4e2a\u5b9e\u53c2\u90fd\u4f7f\u7528\u5bf9\u5e94\u4e8e\u8be5\u53c2\u6570\u6570\u636e\u7c7b\u578b\u7684<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u53d6\u5f97\u3002\uff08\u5728\u975e\u4e25\u683c\u7684\u51fd\u6570\u4e2d\uff0c\u9700\u8981\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u5bf9\u53c2\u6570\u662f\u5426\u4e3a\u7a7a\u503c\u63d0\u524d\u505a\u68c0\u67e5\uff1b\u89c1\u4e0b\u6587\u3002\uff09\u7ed3\u679c\u8981\u7528\u5bf9\u5e94\u4e8e\u8fd4\u56de\u7c7b\u578b\u7684<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u8fd4\u56de\u3002<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u8981\u53d6\u5f97\u7684\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">PG_RETURN_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u7684\u53c2\u6570\u662f\u5b9e\u9645\u8981\u8fd4\u56de\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u8981\u8c03\u7528\u53e6\u4e00\u4e2a\u7248\u672c-1 \u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">DirectFunctionCall<em class=\"replaceable\"><code>n</code></em>(func, arg1, ..., argn)</code>\u3002\u8fd9\u5728\u4f60\u60f3\u8c03\u7528\u6807\u51c6\u5185\u90e8\u5e93\u4e2d\u5b9a\u4e49\u7684\u51fd\u6570\u65f6\u5c24\u5176\u6709\u7528\uff0c\u56e0\u4e3a\u5b83\u63d0\u4f9b\u4e86\u4e0e\u5176 SQL \u7b7e\u540d\u76f8\u4f3c\u7684\u63a5\u53e3\u3002</p>\n<p lang=\"zh\">\u8fd9\u4e9b\u4fbf\u5229\u51fd\u6570\u4ee5\u53ca\u7c7b\u4f3c\u51fd\u6570\u90fd\u53ef\u4ee5\u5728 <code class=\"filename\">fmgr.h</code> \u4e2d\u627e\u5230\u3002<code class=\"function\">DirectFunctionCall<em class=\"replaceable\"><code>n</code></em></code> \u7cfb\u5217\u628a C \u51fd\u6570\u540d\u4f5c\u4e3a\u5176\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\u53e6\u6709 <code class=\"function\">OidFunctionCall<em class=\"replaceable\"><code>n</code></em></code> \u7b49\u4e00\u4e9b\u53d8\u4f53\uff0c\u5b83\u4eec\u63a5\u6536\u76ee\u6807\u51fd\u6570\u7684 OID\u3002\u6240\u6709\u8fd9\u4e9b\u51fd\u6570\u90fd\u8981\u6c42\u4ee5 <code class=\"type\">Datum</code> \u5f62\u5f0f\u63d0\u4f9b\u51fd\u6570\u53c2\u6570\uff0c\u8fd4\u56de\u503c\u4e5f\u540c\u6837\u662f <code class=\"type\">Datum</code>\u3002\u6ce8\u610f\uff0c\u4f7f\u7528\u8fd9\u4e9b\u4fbf\u5229\u51fd\u6570\u65f6\uff0c\u53c2\u6570\u548c\u7ed3\u679c\u90fd\u4e0d\u80fd\u4e3a NULL\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u8981\u5728 C \u4e2d\u8c03\u7528 <code class=\"function\">starts_with(text, text)</code>\uff0c\u4f60\u53ef\u4ee5\u5728\u7cfb\u7edf\u76ee\u5f55\u4e2d\u67e5\u5230\u5b83\u7684 C \u5b9e\u73b0\u662f <code class=\"function\">Datum text_starts_with(PG_FUNCTION_ARGS)</code> \u51fd\u6570\u3002\u901a\u5e38\u4f60\u4f1a\u7528 <code class=\"literal\">DirectFunctionCall2(text_starts_with, ...)</code> \u6765\u8c03\u7528\u5b83\u3002\u4e0d\u8fc7\uff0c<code class=\"function\">starts_with(text, text)</code> \u9700\u8981\u6392\u5e8f\u89c4\u5219\u4fe1\u606f\uff0c\u56e0\u6b64\u5982\u679c\u8fd9\u6837\u8c03\u7528\uff0c\u4f1a\u56e0<span class=\"quote\">\u201c<span class=\"quote\">\u65e0\u6cd5\u786e\u5b9a\u5b57\u7b26\u4e32\u6bd4\u8f83\u8be5\u4f7f\u7528\u54ea\u4e00\u79cd\u6392\u5e8f\u89c4\u5219</span>\u201d</span>\u800c\u5931\u8d25\u3002\u4f60\u5fc5\u987b\u6539\u7528 <code class=\"literal\">DirectFunctionCall2Coll(text_starts_with, ...)</code>\uff0c\u5e76\u63d0\u4f9b\u6240\u9700\u7684\u6392\u5e8f\u89c4\u5219\uff0c\u901a\u5e38\u5c31\u662f\u4ece <code class=\"function\">PG_GET_COLLATION()</code> \u4f20\u9012\u8fdb\u6765\uff0c\u5982\u4e0b\u9762\u7684\u793a\u4f8b\u6240\u793a\u3002</p>\n<p lang=\"zh\"><code class=\"filename\">fmgr.h</code> \u8fd8\u63d0\u4f9b\u4e86\u4fbf\u4e8e\u5728 C \u7c7b\u578b\u548c <code class=\"type\">Datum</code> \u4e4b\u95f4\u8f6c\u6362\u7684\u5b8f\u3002\u4f8b\u5982\uff0c\u8981\u628a <code class=\"type\">Datum</code> \u8f6c\u6210 <code class=\"type\">text*</code>\uff0c\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">DatumGetTextPP(X)</code>\u3002\u867d\u7136\u67d0\u4e9b\u7c7b\u578b\u4e3a\u53cd\u5411\u8f6c\u6362\u63d0\u4f9b\u4e86\u540d\u4e3a <code class=\"function\">TypeGetDatum(X)</code> \u4e4b\u7c7b\u7684\u5b8f\uff0c\u4f46 <code class=\"type\">text*</code> \u6ca1\u6709\uff1b\u5bf9\u5b83\u800c\u8a00\uff0c\u76f4\u63a5\u4f7f\u7528\u901a\u7528\u5b8f <code class=\"function\">PointerGetDatum(X)</code> \u5373\u53ef\u3002\u5982\u679c\u4f60\u7684\u6269\u5c55\u5b9a\u4e49\u4e86\u989d\u5916\u7684\u7c7b\u578b\uff0c\u901a\u5e38\u4e5f\u5f88\u65b9\u4fbf\u4e3a\u8fd9\u4e9b\u7c7b\u578b\u5b9a\u4e49\u7c7b\u4f3c\u7684\u5b8f\u3002</p>\n<p lang=\"zh\">\u4ee5\u4e0b\u662f\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\u7684\u4e00\u4e9b\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include &lt;string.h&gt;\n#include \"fmgr.h\"\n#include \"utils/geo_decls.h\"\n#include \"varatt.h\"\n\nPG_MODULE_MAGIC;\n\n/* by value */\n\nPG_FUNCTION_INFO_V1(add_one);\n\nDatum\nadd_one(PG_FUNCTION_ARGS)\n{\n    int32   arg = PG_GETARG_INT32(0);\n\n    PG_RETURN_INT32(arg + 1);\n}\n\n/* by reference, fixed length */\n\nPG_FUNCTION_INFO_V1(add_one_float8);\n\nDatum\nadd_one_float8(PG_FUNCTION_ARGS)\n{\n    /* The macros for FLOAT8 hide its pass-by-reference nature. */\n    float8   arg = PG_GETARG_FLOAT8(0);\n\n    PG_RETURN_FLOAT8(arg + 1.0);\n}\n\nPG_FUNCTION_INFO_V1(makepoint);\n\nDatum\nmakepoint(PG_FUNCTION_ARGS)\n{\n    /* Here, the pass-by-reference nature of Point is not hidden. */\n    Point     *pointx = PG_GETARG_POINT_P(0);\n    Point     *pointy = PG_GETARG_POINT_P(1);\n    Point     *new_point = (Point *) palloc(sizeof(Point));\n\n    new_point-&gt;x = pointx-&gt;x;\n    new_point-&gt;y = pointy-&gt;y;\n\n    PG_RETURN_POINT_P(new_point);\n}\n\n/* by reference, variable length */\n\nPG_FUNCTION_INFO_V1(copytext);\n\nDatum\ncopytext(PG_FUNCTION_ARGS)\n{\n    text     *t = PG_GETARG_TEXT_PP(0);\n\n    /*\n     * VARSIZE_ANY_EXHDR is the size of the struct in bytes, minus the\n     * VARHDRSZ or VARHDRSZ_SHORT of its header.  Construct the copy with a\n     * full-length header.\n     */\n    text     *new_t = (text *) palloc(VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n    SET_VARSIZE(new_t, VARSIZE_ANY_EXHDR(t) + VARHDRSZ);\n\n    /*\n     * VARDATA is a pointer to the data region of the new struct.  The source\n     * could be a short datum, so retrieve its data through VARDATA_ANY.\n     */\n    memcpy(VARDATA(new_t),          /* destination */\n           VARDATA_ANY(t),          /* source */\n           VARSIZE_ANY_EXHDR(t));   /* how many bytes */\n    PG_RETURN_TEXT_P(new_t);\n}\n\nPG_FUNCTION_INFO_V1(concat_text);\n\nDatum\nconcat_text(PG_FUNCTION_ARGS)\n{\n    text  *arg1 = PG_GETARG_TEXT_PP(0);\n    text  *arg2 = PG_GETARG_TEXT_PP(1);\n    int32 arg1_size = VARSIZE_ANY_EXHDR(arg1);\n    int32 arg2_size = VARSIZE_ANY_EXHDR(arg2);\n    int32 new_text_size = arg1_size + arg2_size + VARHDRSZ;\n    text *new_text = (text *) palloc(new_text_size);\n\n    SET_VARSIZE(new_text, new_text_size);\n    memcpy(VARDATA(new_text), VARDATA_ANY(arg1), arg1_size);\n    memcpy(VARDATA(new_text) + arg1_size, VARDATA_ANY(arg2), arg2_size);\n    PG_RETURN_TEXT_P(new_text);\n}\n\n/* A wrapper around starts_with(text, text) */\n\nPG_FUNCTION_INFO_V1(t_starts_with);\n\nDatum\nt_starts_with(PG_FUNCTION_ARGS)\n{\n    text       *t1 = PG_GETARG_TEXT_PP(0);\n    text       *t2 = PG_GETARG_TEXT_PP(1);\n    Oid         collid = PG_GET_COLLATION();\n    bool        result;\n\n    result = DatumGetBool(DirectFunctionCall2Coll(text_starts_with,\n                                                  collid,\n                                                  PointerGetDatum(t1),\n                                                  PointerGetDatum(t2)));\n    PG_RETURN_BOOL(result);\n}\n\n</pre>\n<p lang=\"zh\">\u5047\u5b9a\u4e0a\u8ff0\u4ee3\u7801\u5df2\u7ecf\u51c6\u5907\u5728\u6587\u4ef6<code class=\"filename\">funcs.c</code>\u4e2d\u5e76\u4e14\u88ab\u7f16\u8bd1\u6210\u4e00\u4e2a\u5171\u4eab\u5bf9\u8c61\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u8fd9\u6837\u7684\u547d\u4ee4\u5728<span class=\"productname\">PostgreSQL</span>\u4e2d\u5b9a\u4e49\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION add_one(integer) RETURNS integer\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one'\n     LANGUAGE C STRICT;\n\n-- note overloading of SQL function name \"add_one\"\nCREATE FUNCTION add_one(double precision) RETURNS double precision\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'add_one_float8'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION makepoint(point, point) RETURNS point\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'makepoint'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION copytext(text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'copytext'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION concat_text(text, text) RETURNS text\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'concat_text'\n     LANGUAGE C STRICT;\n\nCREATE FUNCTION t_starts_with(text, text) RETURNS boolean\n     AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 't_starts_with'\n     LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u8fd9\u91cc\uff0cDIRECTORY \u8868\u793a\u5171\u4eab\u5e93\u6587\u4ef6\u6240\u5728\u76ee\u5f55\uff0c\u4f8b\u5982 PostgreSQL \u6559\u7a0b\u76ee\u5f55\uff0c\u5176\u4e2d\u5305\u542b\u672c\u8282\u793a\u4f8b\u7684\u4ee3\u7801\u3002\uff08\u66f4\u597d\u7684\u5199\u6cd5\u662f\u5148\u5c06 DIRECTORY \u52a0\u5165\u641c\u7d22\u8def\u5f84\uff0c\u518d\u5728 AS \u5b50\u53e5\u4e2d\u4ec5\u5199 'funcs'\u3002\u65e0\u8bba\u54ea\u79cd\u60c5\u51b5\uff0c\u90fd\u53ef\u4ee5\u7701\u7565\u5171\u4eab\u5e93\u7684\u5e73\u53f0\u7279\u5b9a\u6269\u5c55\u540d\uff0c\u901a\u5e38\u4e3a .so\u3002\uff09</p>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u5df2\u7ecf\u628a\u51fd\u6570\u6307\u5b9a\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\uff0c\u8fd9\u610f\u5473\u7740\u5982\u679c\u6709\u4efb\u4f55\u8f93\u5165\u503c\u4e3a\u7a7a\u503c\uff0c\u7cfb\u7edf\u5e94\u8be5\u81ea\u52a8\u5047\u5b9a\u7ed3\u679c\u4e3a\u7a7a\u503c\u3002\u901a\u8fc7\u8fd9\u79cd\u505a\u6cd5\uff0c\u6211\u4eec\u907f\u514d\u5728\u51fd\u6570\u4ee3\u7801\u4e2d\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002\u5982\u679c\u4e0d\u8fd9\u6837\u505a\uff0c\u6211\u4eec\u5fc5\u987b\u4f7f\u7528<code class=\"function\">PG_ARGISNULL()</code>\u660e\u786e\u5730\u68c0\u67e5\u7a7a\u503c\u8f93\u5165\u3002</p>\n<p lang=\"zh\">\u5b8f<code class=\"function\">PG_ARGISNULL(<em class=\"replaceable\"><code>n</code></em>)</code>\u5141\u8bb8\u4e00\u4e2a\u51fd\u6570\u6d4b\u8bd5\u662f\u5426\u6bcf\u4e00\u4e2a\u8f93\u5165\u4e3a\u7a7a\u503c\uff08\u5f53\u7136\uff0c\u53ea\u9700\u8981\u5728\u6ca1\u6709\u58f0\u660e\u4e3a<span class=\"quote\">\u201c<span class=\"quote\">strict</span>\u201d</span>\u7684\u51fd\u6570\u4e2d\u8fd9\u6837\u505a\uff09\u3002\u548c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u5b8f\u4e00\u6837\uff0c\u8f93\u5165\u53c2\u6570\u4e5f\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u6570\u3002\u6ce8\u610f\u5e94\u8be5\u5728\u9a8c\u8bc1\u4e86\u4e00\u4e2a\u53c2\u6570\u4e0d\u662f\u7a7a\u503c\u4e4b\u540e\u624d\u6267\u884c<code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em>()</code>\u3002\u8981\u8fd4\u56de\u7a7a\u503c\u7ed3\u679c\uff0c\u5e94\u6267\u884c<code class=\"function\">PG_RETURN_NULL()</code>\uff0c\u5b83\u5bf9\u4e25\u683c\u7684\u4ee5\u53ca\u975e\u4e25\u683c\u7684\u51fd\u6570\u90fd\u6709\u7528\u3002</p>\n<p lang=\"zh\">\u4e4d\u770b\u4e4b\u4e0b\uff0c\u4e0e\u666e\u901a\u7684 <code class=\"literal\">C</code> \u8c03\u7528\u7ea6\u5b9a\u76f8\u6bd4\uff0c\u7248\u672c 1 \u7684\u7f16\u7801\u7ea6\u5b9a\u4f3c\u4e4e\u53ea\u662f\u589e\u52a0\u4e86\u590d\u6742\u5ea6\u3002\u4e0d\u8fc7\uff0c\u5b83\u4eec\u786e\u5b9e\u8ba9\u6211\u4eec\u80fd\u591f\u5904\u7406\u53ef\u4e3a <code class=\"literal\">NULL</code> \u7684\u53c2\u6570\u548c\u8fd4\u56de\u503c\uff0c\u4ee5\u53ca<span class=\"quote\">\u201c<span class=\"quote\">\u7ecf\u8fc7 TOAST \u5904\u7406</span>\u201d</span>\uff08\u538b\u7f29\u6216\u884c\u5916\uff09\u7684\u503c\u3002</p>\n<p lang=\"zh\">\u7248\u672c 1 \u63a5\u53e3\u8fd8\u63d0\u4f9b\u4e86\u4e24\u79cd PG_GETARG_xxx() \u5b8f\u53d8\u4f53\u3002\u7b2c\u4e00\u79cd PG_GETARG_xxx_COPY() \u4fdd\u8bc1\u8fd4\u56de\u6307\u5b9a\u53c2\u6570\u7684\u53ef\u5199\u526f\u672c\u3002\u666e\u901a\u5b8f\u6709\u65f6\u4f1a\u8fd4\u56de\u6307\u5411\u8868\u4e2d\u7269\u7406\u5b58\u50a8\u503c\u7684\u6307\u9488\uff0c\u7981\u6b62\u5199\u5165\uff1b\u4f7f\u7528 PG_GETARG_xxx_COPY() \u5219\u53ef\u4fdd\u8bc1\u7ed3\u679c\u53ef\u5199\u3002\u7b2c\u4e8c\u79cd\u662f\u63a5\u53d7\u4e09\u4e2a\u53c2\u6570\u7684 PG_GETARG_xxx_SLICE() \u5b8f\uff1a\u7b2c\u4e00\u4e2a\u53c2\u6570\u662f\u51fd\u6570\u53c2\u6570\u7684\u7f16\u53f7\uff0c\u5982\u4e0a\u6587\u6240\u8ff0\uff1b\u7b2c\u4e8c\u3001\u4e09\u4e2a\u53c2\u6570\u5206\u522b\u662f\u8981\u8fd4\u56de\u7247\u6bb5\u7684\u504f\u79fb\u91cf\u548c\u957f\u5ea6\u3002\u504f\u79fb\u91cf\u4ece\u96f6\u5f00\u59cb\uff0c\u8d1f\u957f\u5ea6\u8868\u793a\u8fd4\u56de\u8be5\u503c\u7684\u5269\u4f59\u90e8\u5206\u3002\u5bf9\u4e8e\u5b58\u50a8\u7c7b\u578b\u4e3a external \u7684\u5927\u503c\uff0c\u8fd9\u4e9b\u5b8f\u53ef\u66f4\u9ad8\u6548\u5730\u8bbf\u95ee\u5176\u4e2d\u4e00\u90e8\u5206\u3002\u5217\u7684\u5b58\u50a8\u7c7b\u578b\u53ef\u901a\u8fc7 ALTER TABLE tablename ALTER COLUMN colname SET STORAGE storagetype \u6307\u5b9a\uff0c\u5176\u4e2d storagetype \u4e3a plain\u3001external\u3001extended \u6216 main \u4e4b\u4e00\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u7248\u672c-1 \u7684\u51fd\u6570\u8c03\u7528\u7ea6\u5b9a\u53ef\u4ee5\u8fd4\u56de\u96c6\u5408\u7ed3\u679c\uff08<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-RETURN-SET\" title=\"36.10.9.\u00a0\u8fd4\u56de\u96c6\u5408\">\u7b2c\u00a036.10.9\u00a0\u8282</a>\uff09\u3001\u5b9e\u73b0\u89e6\u53d1\u5668\u51fd\u6570\uff08<a class=\"xref\" href=\"/docs/18/triggers.html\" title=\"\u7b2c\u00a037\u00a0\u7ae0\u00a0\u89e6\u53d1\u5668\">\u7b2c\u00a037\u00a0\u7ae0</a>\uff09\u548c\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\uff08<a class=\"xref\" href=\"/docs/18/plhandler.html\" title=\"\u7b2c\u00a057\u00a0\u7ae0\u00a0\u7f16\u5199\u8fc7\u7a0b\u8bed\u8a00\u8c03\u7528\u5904\u7406\u5668\">\u7b2c\u00a057\u00a0\u7ae0</a>\uff09\u3002\u66f4\u591a\u7ec6\u8282\u53ef\u89c1\u6e90\u4ee3\u7801\u53d1\u5e03\u4e2d\u7684<code class=\"filename\">src/backend/utils/fmgr/README</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-CODE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-CODE\">36.10.4. \u7f16\u5199\u4ee3\u7801</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u5f00\u59cb\u66f4\u9ad8\u7ea7\u7684\u8bdd\u9898\u4e4b\u524d\uff0c\u6211\u4eec\u5e94\u8be5\u8ba8\u8bba\u4e00\u4e0b\u7528\u4e8e <span class=\"productname\">PostgreSQL</span> C \u8bed\u8a00\u51fd\u6570\u7684\u7f16\u7801\u89c4\u5219\u3002\u867d\u7136\u6709\u53ef\u80fd\u628a\u4e0d\u662f C \u7f16\u5199\u7684\u51fd\u6570\u8f7d\u5165\u5230 <span class=\"productname\">PostgreSQL</span>\u4e2d\uff0c\u4f46\u5373\u4f7f\u80fd\u591f\u505a\u5230\uff0c\u901a\u5e38\u4e5f\u5f88\u56f0\u96be\uff0c\u56e0\u4e3a\u5176\u4ed6\u8bed\u8a00\uff08\u4f8b\u5982 C++\u3001FORTRAN \u6216\u8005 Pascal\uff09\u901a\u5e38\u4e0d\u4f1a\u9075\u5faa\u548c C \u76f8\u540c\u7684\u8c03\u7528\u7ea6\u5b9a\u3002\u4e5f\u5c31\u662f\u8bf4\uff0c\u5176\u4ed6\u8bed\u8a00\u4e0d\u4f1a\u4ee5\u540c\u6837\u7684\u65b9\u5f0f\u5728\u51fd\u6570\u4e4b\u95f4\u4f20\u9012\u53c2\u6570\u4ee5\u53ca\u8fd4\u56de\u503c\u3002\u7531\u4e8e\u8fd9\u4e2a\u539f\u56e0\uff0c\u6211\u4eec\u4f1a\u5047\u5b9a\u4f60\u7684 C \u8bed\u8a00\u51fd\u6570\u786e\u5b9e\u662f\u7528 C \u7f16\u5199\u7684\u3002</p>\n<p lang=\"zh\">\u7f16\u5199\u548c\u6784\u5efa C \u8bed\u8a00\u51fd\u6570\u7684\u57fa\u672c\u89c4\u5219\u5982\u4e0b\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528 <code class=\"literal\">pg_config --includedir-server</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.1.1.2\" name=\"id-1.8.3.13.8.3.1.1.1.2\"></a> \u67e5\u51fa <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u5934\u6587\u4ef6\u5728\u4f60\u7684\u7cfb\u7edf\u4e0a\uff08\u6216\u4f60\u7684\u7528\u6237\u5c06\u8981\u8fd0\u884c\u7684\u7cfb\u7edf\u4e0a\uff09\u5b89\u88c5\u4e8e\u4f55\u5904\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4e3a\u4e86\u8ba9\u4f60\u7684\u4ee3\u7801\u80fd\u591f\u88ab <span class=\"productname\">PostgreSQL</span> \u52a8\u6001\u88c5\u5165\uff0c\u7f16\u8bd1\u548c\u94fe\u63a5\u65f6\u603b\u662f\u9700\u8981\u7279\u6b8a\u7684\u9009\u9879\u3002\u5173\u4e8e\u5982\u4f55\u5728\u7279\u5b9a\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u5b8c\u6210\u8fd9\u4ef6\u4e8b\uff0c\u8be6\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#DFUNC\" title=\"36.10.5.\u00a0\u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570\">\u7b2c\u00a036.10.5\u00a0\u8282</a>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u8bb0\u5f97\u6309\u7167<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u4e2d\u7684\u8bf4\u660e\uff0c\u4e3a\u4f60\u7684\u5171\u4eab\u5e93\u5b9a\u4e49\u4e00\u4e2a<span class=\"quote\">\u201c<span class=\"quote\">\u9b54\u6570\u5757</span>\u201d</span>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u5206\u914d\u5185\u5b58\u65f6\uff0c\u4f7f\u7528 <span class=\"productname\">PostgreSQL</span> \u63d0\u4f9b\u7684 <code class=\"function\">palloc</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.3\" name=\"id-1.8.3.13.8.3.1.4.1.3\"></a> \u548c <code class=\"function\">pfree</code><a class=\"indexterm\" id=\"id-1.8.3.13.8.3.1.4.1.5\" name=\"id-1.8.3.13.8.3.1.4.1.5\"></a>\uff0c\u800c\u4e0d\u662f\u76f8\u5e94\u7684 C \u5e93\u51fd\u6570 <code class=\"function\">malloc</code> \u548c <code class=\"function\">free</code>\u3002\u7528 <code class=\"function\">palloc</code> \u5206\u914d\u7684\u5185\u5b58\u4f1a\u5728\u6bcf\u4e2a\u4e8b\u52a1\u7ed3\u675f\u65f6\u81ea\u52a8\u91ca\u653e\uff0c\u4ece\u800c\u907f\u514d\u5185\u5b58\u6cc4\u6f0f\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u603b\u662f\u4f7f\u7528 <code class=\"function\">memset</code> \u5c06\u7ed3\u6784\u4f53\u7684\u6240\u6709\u5b57\u8282\u6e05\u96f6\uff08\u6216\u8005\u4e00\u5f00\u59cb\u5c31\u7528 <code class=\"function\">palloc0</code> \u6765\u5206\u914d\u5b83\u4eec\uff09\u3002\u5373\u4f7f\u4f60\u7ed9\u7ed3\u6784\u4f53\u7684\u6bcf\u4e2a\u5b57\u6bb5\u90fd\u8d4b\u4e86\u503c\uff0c\u7ed3\u6784\u4f53\u4e2d\u4ecd\u53ef\u80fd\u5b58\u5728\u5305\u542b\u5783\u573e\u503c\u7684\u5bf9\u9f50\u586b\u5145\u5b57\u8282\uff08\u4e5f\u5c31\u662f\u7ed3\u6784\u4f53\u4e2d\u7684\u7a7a\u6d1e\uff09\u3002\u5982\u679c\u4e0d\u8fd9\u4e48\u505a\uff0c\u5c31\u5f88\u96be\u652f\u6301 hash \u7d22\u5f15\u6216\u54c8\u5e0c\u8fde\u63a5\uff0c\u56e0\u4e3a\u90a3\u65f6\u4f60\u5fc5\u987b\u53ea\u6311\u51fa\u6570\u636e\u7ed3\u6784\u4e2d\u771f\u6b63\u6709\u610f\u4e49\u7684\u4f4d\u6765\u8ba1\u7b97 hash \u503c\u3002\u89c4\u5212\u5668\u6709\u65f6\u4e5f\u4f9d\u8d56\u6309\u4f4d\u76f8\u7b49\u6765\u6bd4\u8f83\u5e38\u91cf\uff0c\u56e0\u6b64\u5982\u679c\u903b\u8f91\u4e0a\u7b49\u4ef7\u7684\u503c\u5728\u6309\u4f4d\u4e0a\u4e0d\u76f8\u7b49\uff0c\u5c31\u53ef\u80fd\u5f97\u5230\u4e0d\u7406\u60f3\u7684\u89c4\u5212\u7ed3\u679c\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p><span class=\"productname\">PostgreSQL</span> \u7684\u5927\u591a\u6570\u5185\u90e8\u7c7b\u578b\u90fd\u5728 <code class=\"filename\">postgres.h</code> \u4e2d\u58f0\u660e\uff0c\u800c\u51fd\u6570\u7ba1\u7406\u5668\u63a5\u53e3\uff08<code class=\"symbol\">PG_FUNCTION_ARGS</code> \u7b49\uff09\u4f4d\u4e8e <code class=\"filename\">fmgr.h</code> \u4e2d\uff0c\u56e0\u6b64\u81f3\u5c11\u9700\u8981\u5305\u542b\u8fd9\u4e24\u4e2a\u6587\u4ef6\u3002\u51fa\u4e8e\u53ef\u79fb\u690d\u6027\u8003\u8651\uff0c\u6700\u597d\u628a <code class=\"filename\">postgres.h</code> \u653e\u5728<span class=\"emphasis\"><em>\u6700\u524d\u9762</em></span>\uff0c\u5148\u4e8e\u4efb\u4f55\u5176\u4ed6\u7cfb\u7edf\u6216\u7528\u6237\u5934\u6587\u4ef6\u3002\u5305\u542b <code class=\"filename\">postgres.h</code> \u65f6\uff0c\u4e5f\u4f1a\u987a\u5e26\u4e3a\u4f60\u5305\u542b <code class=\"filename\">elog.h</code> \u548c <code class=\"filename\">palloc.h</code>\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u76ee\u6807\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u540d\u4e0d\u80fd\u5f7c\u6b64\u51b2\u7a81\uff0c\u4e5f\u4e0d\u80fd\u4e0e <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668\u53ef\u6267\u884c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u7684\u7b26\u53f7\u51b2\u7a81\u3002\u5982\u679c\u4f60\u6536\u5230\u8fd9\u7c7b\u9519\u8bef\u6d88\u606f\uff0c\u5c31\u5fc5\u987b\u91cd\u547d\u540d\u76f8\u5173\u51fd\u6570\u6216\u53d8\u91cf\u3002</p>\n</li>\n</ul>\n</div>\n</div>\n<div class=\"sect2\" id=\"DFUNC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#DFUNC\">36.10.5. \u7f16\u8bd1\u548c\u94fe\u63a5\u52a8\u6001\u88c5\u8f7d\u51fd\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728\u4f60\u80fd\u591f\u4f7f\u7528\u4ee5 C \u7f16\u5199\u7684 <span class=\"productname\">PostgreSQL</span> \u6269\u5c55\u51fd\u6570\u4e4b\u524d\uff0c\u5fc5\u987b\u4ee5\u7279\u6b8a\u65b9\u5f0f\u5bf9\u5b83\u4eec\u8fdb\u884c\u7f16\u8bd1\u548c\u94fe\u63a5\uff0c\u4ee5\u751f\u6210\u4e00\u4e2a\u53ef\u7531\u670d\u52a1\u5668\u52a8\u6001\u88c5\u8f7d\u7684\u6587\u4ef6\u3002\u66f4\u51c6\u786e\u5730\u8bf4\uff0c\u9700\u8981\u521b\u5efa\u4e00\u4e2a<em class=\"firstterm\">\u5171\u4eab\u5e93</em>\u3002<a class=\"indexterm\" id=\"id-1.8.3.13.9.2.3\" name=\"id-1.8.3.13.9.2.3\"></a></p>\n<p lang=\"zh\">\u82e5\u60f3\u4e86\u89e3\u672c\u8282\u672a\u6db5\u76d6\u7684\u4fe1\u606f\uff0c\u4f60\u5e94\u9605\u8bfb\u64cd\u4f5c\u7cfb\u7edf\u7684\u6587\u6863\uff0c\u7279\u522b\u662f C \u7f16\u8bd1\u5668 <code class=\"command\">cc</code> \u548c\u94fe\u63a5\u7f16\u8f91\u5668 <code class=\"command\">ld</code> \u7684\u624b\u518c\u9875\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u5728 <code class=\"filename\">contrib</code> \u76ee\u5f55\u4e2d\u5305\u542b\u82e5\u5e72\u53ef\u7528\u7684\u793a\u4f8b\u3002\u4e0d\u8fc7\uff0c\u5982\u679c\u4f60\u4f9d\u8d56\u8fd9\u4e9b\u793a\u4f8b\uff0c\u5c31\u4f1a\u4f7f\u4f60\u7684\u6a21\u5757\u4f9d\u8d56\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u662f\u5426\u53ef\u7528\u3002</p>\n<p lang=\"zh\">\u521b\u5efa\u5171\u4eab\u5e93\u901a\u5e38\u7c7b\u4f3c\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\uff1a\u5148\u5c06\u6e90\u6587\u4ef6\u7f16\u8bd1\u4e3a\u76ee\u6807\u6587\u4ef6\uff0c\u518d\u5c06\u76ee\u6807\u6587\u4ef6\u94fe\u63a5\u8d77\u6765\u3002\u76ee\u6807\u6587\u4ef6\u9700\u8981\u7f16\u8bd1\u4e3a\u4f4d\u7f6e\u65e0\u5173\u4ee3\u7801\uff08PIC\uff09\uff0c\u4e5f\u5c31\u662f\u5728\u6982\u5ff5\u4e0a\u5141\u8bb8\u53ef\u6267\u884c\u6587\u4ef6\u52a0\u8f7d\u5b83\u4eec\u65f6\u5c06\u5176\u653e\u5728\u5185\u5b58\u4e2d\u7684\u4efb\u610f\u4f4d\u7f6e\u3002\uff08\u7528\u4e8e\u53ef\u6267\u884c\u6587\u4ef6\u7684\u76ee\u6807\u6587\u4ef6\u901a\u5e38\u4e0d\u8fd9\u6837\u7f16\u8bd1\u3002\uff09\u94fe\u63a5\u5171\u4eab\u5e93\u7684\u547d\u4ee4\u5305\u542b\u7279\u6b8a\u6807\u5fd7\uff0c\u7528\u6765\u533a\u522b\u4e8e\u94fe\u63a5\u53ef\u6267\u884c\u6587\u4ef6\u7684\u547d\u4ee4\u2014\u2014\u81f3\u5c11\u7406\u8bba\u4e0a\u5982\u6b64\uff0c\u67d0\u4e9b\u7cfb\u7edf\u7684\u5b9e\u9645\u505a\u6cd5\u8981\u590d\u6742\u5f97\u591a\u3002</p>\n<p lang=\"zh\">\u5728\u4e0b\u9762\u7684\u793a\u4f8b\u4e2d\uff0c\u6211\u4eec\u5047\u5b9a\u4f60\u7684\u6e90\u4ee3\u7801\u4f4d\u4e8e\u6587\u4ef6 <code class=\"filename\">foo.c</code> \u4e2d\uff0c\u5e76\u5c06\u521b\u5efa\u5171\u4eab\u5e93 <code class=\"filename\">foo.so</code>\u3002\u9664\u975e\u53e6\u6709\u8bf4\u660e\uff0c\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u4e3a <code class=\"filename\">foo.o</code>\u3002\u5171\u4eab\u5e93\u53ef\u4ee5\u5305\u542b\u591a\u4e2a\u76ee\u6807\u6587\u4ef6\uff0c\u4f46\u8fd9\u91cc\u6211\u4eec\u53ea\u4f7f\u7528\u4e00\u4e2a\u3002</p>\n<div class=\"variablelist\">\n<dl class=\"variablelist\">\n<dt><span class=\"term\"><span class=\"systemitem\">FreeBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u65f6\u4f7f\u7528\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u8fd9\u4ece <span class=\"systemitem\">FreeBSD</span> 13.0 \u8d77\u9002\u7528\uff1b\u66f4\u65e9\u7248\u672c\u4f7f\u7528\u7684\u662f <code class=\"filename\">gcc</code> \u7f16\u8bd1\u5668\u3002</p>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Linux</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u521b\u5efa\u5171\u4eab\u5e93\u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-shared</code>\u3002\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">cc -fPIC -c foo.c\ncc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">macOS</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b\u3002\u5b83\u5047\u5b9a\u5f00\u53d1\u8005\u5de5\u5177\u5df2\u7ecf\u5b89\u88c5\u3002</p>\n<pre class=\"programlisting\">cc -c foo.c\ncc -bundle -flat_namespace -undefined suppress -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">NetBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u5bf9\u4e8e <acronym class=\"acronym\">ELF</acronym> \u7cfb\u7edf\uff0c\u4f7f\u7528\u5e26\u6709 <code class=\"option\">-shared</code> \u9009\u9879\u7684\u7f16\u8bd1\u5668\u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002\u5bf9\u4e8e\u8f83\u65e9\u7684\u975e ELF \u7cfb\u7edf\uff0c\u5219\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code>\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -shared -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">OpenBSD</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\u662f <code class=\"option\">-fPIC</code>\u3002\u4f7f\u7528 <code class=\"literal\">ld -Bshareable</code> \u6765\u94fe\u63a5\u5171\u4eab\u5e93\u3002</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\nld -Bshareable -o foo.so foo.o\n</pre>\n</dd>\n<dt><span class=\"term\"><span class=\"systemitem\">Solaris</span> </span></dt>\n<dd>\n<p lang=\"zh\">\u751f\u6210 <acronym class=\"acronym\">PIC</acronym> \u7684\u7f16\u8bd1\u5668\u9009\u9879\uff0c\u5bf9\u4e8e Sun \u7f16\u8bd1\u5668\u662f <code class=\"option\">-KPIC</code>\uff0c\u800c <code class=\"option\">-fPIC</code> \u5219\u7528\u4e8e <span class=\"application\">GCC</span>\u3002\u94fe\u63a5\u5171\u4eab\u5e93\u65f6\uff0c\u4e24\u79cd\u7f16\u8bd1\u5668\u90fd\u53ef\u4ee5\u4f7f\u7528 <code class=\"option\">-G</code>\uff0c\u6216\u8005\u4e5f\u53ef\u4ee5\u6539\u7528 <code class=\"option\">-shared</code>\uff0c\u4f46\u8fd9\u53ea\u9002\u7528\u4e8e <span class=\"application\">GCC</span>\u3002</p>\n<pre class=\"programlisting\">cc -KPIC -c foo.c\ncc -G -o foo.so foo.o\n</pre>\n<p lang=\"zh\">\u6216\u8005</p>\n<pre class=\"programlisting\">gcc -fPIC -c foo.c\ngcc -G -o foo.so foo.o\n</pre>\n</dd>\n</dl>\n</div>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\">\u5982\u679c\u8fd9\u4e9b\u5185\u5bb9\u5bf9\u4f60\u6765\u8bf4\u8fc7\u4e8e\u590d\u6742\uff0c\u53ef\u4ee5\u8003\u8651\u4f7f\u7528 <a class=\"ulink\" href=\"https://www.gnu.org/software/libtool/\" target=\"_top\"><span class=\"productname\">GNU Libtool</span></a>\uff0c\u5b83\u901a\u8fc7\u7edf\u4e00\u63a5\u53e3\u9690\u85cf\u4e86\u5e73\u53f0\u5dee\u5f02\u3002</p>\n</div>\n<p lang=\"zh\">\u751f\u6210\u7684\u5171\u4eab\u5e93\u6587\u4ef6\u968f\u540e\u5c31\u53ef\u4ee5\u88c5\u8f7d\u5230 <span class=\"productname\">PostgreSQL</span> \u4e2d\u3002\u5728\u5411 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u6307\u5b9a\u6587\u4ef6\u540d\u65f6\uff0c\u5fc5\u987b\u7ed9\u51fa\u5171\u4eab\u5e93\u6587\u4ef6\u540d\uff0c\u800c\u4e0d\u662f\u4e2d\u95f4\u76ee\u6807\u6587\u4ef6\u540d\u3002\u8bf7\u6ce8\u610f\uff0c\u7cfb\u7edf\u6807\u51c6\u7684\u5171\u4eab\u5e93\u6269\u5c55\u540d\uff08\u901a\u5e38\u662f <code class=\"literal\">.so</code> \u6216 <code class=\"literal\">.sl</code>\uff09\u53ef\u4ee5\u5728 <code class=\"command\">CREATE FUNCTION</code> \u547d\u4ee4\u4e2d\u7701\u7565\uff0c\u5e76\u4e14\u901a\u5e38\u4e5f\u5e94\u7701\u7565\uff0c\u4ee5\u83b7\u5f97\u6700\u4f73\u53ef\u79fb\u690d\u6027\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e\u670d\u52a1\u5668\u671f\u671b\u5728\u4f55\u5904\u627e\u5230\u5171\u4eab\u5e93\u6587\u4ef6\uff0c\u8bf7\u56de\u5934\u53c2\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-API-ABI-STABILITY-GUIDANCE\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-API-ABI-STABILITY-GUIDANCE\">36.10.6. \u670d\u52a1\u5668 API \u548c ABI \u7a33\u5b9a\u6027\u6307\u5357</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u672c\u8282\u5411\u6269\u5c55\u548c\u5176\u4ed6\u670d\u52a1\u5668\u63d2\u4ef6\u7684\u4f5c\u8005\u63d0\u4f9b\u6709\u5173 <span class=\"productname\">PostgreSQL</span> \u670d\u52a1\u5668 API \u4e0e ABI \u7a33\u5b9a\u6027\u7684\u6307\u5bfc\u3002</p>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-GENERAL\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.1.\u00a0\u6982\u8ff0 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">PostgreSQL \u670d\u52a1\u5668\u4e3a\u63d2\u4ef6\u63d0\u4f9b\u4e86\u591a\u4e2a\u8fb9\u754c\u6e05\u6670\u7684 API\uff0c\u4f8b\u5982\u672c\u7ae0\u4ecb\u7ecd\u7684\u51fd\u6570\u7ba1\u7406\u5668 fmgr\u3001SPI\uff08\u7b2c 45 \u7ae0\uff09\u4ee5\u53ca\u4e13\u4e3a\u6269\u5c55\u8bbe\u8ba1\u7684\u5404\u79cd\u94a9\u5b50\u3002\u8fd9\u4e9b\u63a5\u53e3\u7ecf\u8fc7\u8c28\u614e\u7ef4\u62a4\uff0c\u4ee5\u4fdd\u6301\u957f\u671f\u7a33\u5b9a\u6027\u548c\u517c\u5bb9\u6027\u3002\u4e0d\u8fc7\uff0c\u670d\u52a1\u5668\u4e2d\u5168\u90e8\u5168\u5c40\u51fd\u6570\u548c\u53d8\u91cf\u5b9e\u9645\u4e0a\u90fd\u6784\u6210\u4e86\u53ef\u516c\u5f00\u4f7f\u7528\u7684 API\uff0c\u5176\u4e2d\u5927\u90e8\u5206\u5728\u8bbe\u8ba1\u65f6\u5e76\u672a\u8003\u8651\u53ef\u6269\u5c55\u6027\u548c\u957f\u671f\u7a33\u5b9a\u6027\u3002</p>\n<p lang=\"zh\">\u56e0\u6b64\uff0c\u867d\u7136\u4f7f\u7528\u8fd9\u4e9b\u63a5\u53e3\u662f\u5b8c\u5168\u5141\u8bb8\u7684\uff0c\u4f46\u8d8a\u662f\u504f\u79bb\u90a3\u4e9b\u4e45\u7ecf\u5b9e\u8df5\u8003\u9a8c\u7684\u8def\u5f84\uff0c\u5c06\u6765\u9047\u5230 API \u6216 ABI \u517c\u5bb9\u6027\u95ee\u9898\u7684\u53ef\u80fd\u6027\u5c31\u8d8a\u5927\u3002\u9f13\u52b1\u6269\u5c55\u4f5c\u8005\u53cd\u9988\u81ea\u5df1\u7684\u9700\u6c42\uff0c\u4ee5\u4fbf\u968f\u7740\u65f6\u95f4\u63a8\u79fb\u548c\u65b0\u7528\u6cd5\u7684\u51fa\u73b0\uff0c\u67d0\u4e9b\u63a5\u53e3\u80fd\u591f\u88ab\u89c6\u4e3a\u66f4\u7a33\u5b9a\uff0c\u6216\u8005\u53ef\u4ee5\u52a0\u5165\u65b0\u7684\u3001\u8bbe\u8ba1\u66f4\u5b8c\u5584\u7684\u63a5\u53e3\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-API-COMPATIBILITY\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.2.\u00a0API \u517c\u5bb9\u6027 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">API\uff0c\u5373\u5e94\u7528\u7a0b\u5e8f\u7f16\u7a0b\u63a5\u53e3\uff0c\u662f\u7f16\u8bd1\u65f6\u4f7f\u7528\u7684\u63a5\u53e3\u3002</p>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-API-MAJOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.2.1.\u00a0Major Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5728 <span class=\"productname\">PostgreSQL</span> \u4e0d\u540c\u4e3b\u7248\u672c\u4e4b\u95f4\uff0c<span class=\"emphasis\"><em>\u4e0d\u627f\u8bfa</em></span> API \u517c\u5bb9\u6027\u3002\u56e0\u6b64\uff0c\u6269\u5c55\u4ee3\u7801\u53ef\u80fd\u9700\u8981\u4fee\u6539\u6e90\u4ee3\u7801\u624d\u80fd\u540c\u65f6\u652f\u6301\u591a\u4e2a\u4e3b\u7248\u672c\u3002\u8fd9\u7c7b\u5dee\u5f02\u901a\u5e38\u53ef\u4ee5\u901a\u8fc7\u9884\u5904\u7406\u5668\u6761\u4ef6\uff08\u4f8b\u5982 <code class=\"literal\">#if PG_VERSION_NUM &gt;= 160000</code>\uff09\u6765\u7ba1\u7406\u3002\u90a3\u4e9b\u4f7f\u7528\u4e86\u8fb9\u754c\u6e05\u6670\u63a5\u53e3\u4e4b\u5916\u80fd\u529b\u7684\u590d\u6742\u6269\u5c55\uff0c\u901a\u5e38\u6bcf\u4e2a\u670d\u52a1\u5668\u4e3b\u7248\u672c\u90fd\u9700\u8981\u505a\u5c11\u91cf\u8fd9\u7c7b\u4fee\u6539\u3002</p>\n</div>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-API-MNINOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.2.2.\u00a0Minor Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u529b\u907f\u514d\u5728\u5c0f\u7248\u672c\u53d1\u5e03\u4e2d\u7834\u574f\u670d\u52a1\u5668 API\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u80fd\u9488\u5bf9\u67d0\u4e2a\u5c0f\u7248\u672c\u7f16\u8bd1\u5e76\u6b63\u5e38\u5de5\u4f5c\u7684\u6269\u5c55\u4ee3\u7801\uff0c\u4e5f\u5e94\u5f53\u80fd\u591f\u9488\u5bf9\u540c\u4e00\u4e3b\u7248\u672c\u7684\u5176\u4ed6\u4efb\u610f\u5c0f\u7248\u672c\uff08\u65e0\u8bba\u8fc7\u53bb\u8fd8\u662f\u5c06\u6765\uff09\u7f16\u8bd1\u5e76\u6b63\u5e38\u5de5\u4f5c\u3002</p>\n<p lang=\"zh\">\u5982\u679c<span class=\"emphasis\"><em>\u786e\u5b9e</em></span>\u9700\u8981\u505a\u51fa\u53d8\u66f4\uff0c\u4e5f\u4f1a\u5728\u8003\u8651\u6269\u5c55\u9700\u6c42\u7684\u524d\u63d0\u4e0b\u8c28\u614e\u7ba1\u7406\u3002\u8fd9\u7c7b\u53d8\u66f4\u4f1a\u5728\u53d1\u5e03\u8bf4\u660e\uff08<a class=\"xref\" href=\"/docs/18/release.html\" title=\"\u9644\u5f55\u00a0E.\u00a0\u53d1\u5e03\u8bf4\u660e\">\u9644\u5f55\u00a0E</a>\uff09\u4e2d\u8fdb\u884c\u8bf4\u660e\u3002</p>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-GUIDANCE-ABI-COMPATIBILITY\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.6.3.\u00a0ABI \u517c\u5bb9\u6027 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">ABI\uff0c\u5373\u5e94\u7528\u7a0b\u5e8f\u4e8c\u8fdb\u5236\u63a5\u53e3\uff0c\u662f\u8fd0\u884c\u65f6\u4f7f\u7528\u7684\u63a5\u53e3\u3002</p>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-ABI-MAJOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.3.1.\u00a0Major Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u4e0d\u540c\u4e3b\u7248\u672c\u7684\u670d\u52a1\u5668\u5728 ABI \u4e0a\u662f\u6709\u610f\u4e0d\u517c\u5bb9\u7684\u3002\u56e0\u6b64\uff0c\u4f7f\u7528\u670d\u52a1\u5668 API \u7684\u6269\u5c55\u5fc5\u987b\u9488\u5bf9\u6bcf\u4e00\u4e2a\u4e3b\u7248\u672c\u91cd\u65b0\u7f16\u8bd1\u3002\u5305\u542b <code class=\"literal\">PG_MODULE_MAGIC</code>\uff08\u89c1<a class=\"xref\" href=\"/docs/18/xfunc-c.html#XFUNC-C-DYNLOAD\" title=\"36.10.1.\u00a0\u52a8\u6001\u8f7d\u5165\">\u7b2c\u00a036.10.1\u00a0\u8282</a>\uff09\u53ef\u4ee5\u786e\u4fdd\u9488\u5bf9\u67d0\u4e2a\u4e3b\u7248\u672c\u7f16\u8bd1\u7684\u4ee3\u7801\u4f1a\u88ab\u5176\u4ed6\u4e3b\u7248\u672c\u62d2\u7edd\u3002</p>\n</div>\n<div class=\"sect4\" id=\"XFUNC-GUIDANCE-ABI-MNINOR-VERSIONS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h5 class=\"title\">36.10.6.3.2.\u00a0Minor Versions </h5>\n</div>\n</div>\n</div>\n<p lang=\"zh\"><span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u529b\u907f\u514d\u5728\u5c0f\u7248\u672c\u53d1\u5e03\u4e2d\u7834\u574f\u670d\u52a1\u5668 ABI\u3002\u4e00\u822c\u6765\u8bf4\uff0c\u9488\u5bf9\u4efb\u610f\u4e00\u4e2a\u5c0f\u7248\u672c\u7f16\u8bd1\u7684\u6269\u5c55\uff0c\u5e94\u5f53\u80fd\u4e0e\u540c\u4e00\u4e3b\u7248\u672c\u8fc7\u53bb\u6216\u5c06\u6765\u7684\u5176\u4ed6\u4efb\u610f\u5c0f\u7248\u672c\u4e00\u8d77\u5de5\u4f5c\u3002</p>\n<p lang=\"zh\">\u5982\u679c<span class=\"emphasis\"><em>\u786e\u5b9e</em></span>\u9700\u8981\u53d8\u66f4\uff0c<span class=\"productname\">PostgreSQL</span> \u4f1a\u5c3d\u91cf\u9009\u62e9\u4fb5\u5165\u6027\u6700\u5c0f\u7684\u65b9\u5f0f\uff0c\u4f8b\u5982\u628a\u65b0\u5b57\u6bb5\u585e\u8fdb\u586b\u5145\u7a7a\u95f4\uff0c\u6216\u8005\u9644\u52a0\u5230\u7ed3\u6784\u4f53\u672b\u5c3e\u3002\u8fd9\u7c7b\u4fee\u6539\u901a\u5e38\u4e0d\u5e94\u5f71\u54cd\u6269\u5c55\uff0c\u9664\u975e\u6269\u5c55\u4f7f\u7528\u4e86\u975e\u5e38\u4e0d\u5bfb\u5e38\u7684\u4ee3\u7801\u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u7136\u800c\uff0c\u5728\u6781\u5c11\u6570\u60c5\u51b5\u4e0b\uff0c\u5373\u4f7f\u662f\u8fd9\u79cd\u975e\u4fb5\u5165\u5f0f\u53d8\u66f4\u4e5f\u53ef\u80fd\u4e0d\u73b0\u5b9e\u751a\u81f3\u4e0d\u53ef\u80fd\u505a\u5230\u3002\u53d1\u751f\u8fd9\u79cd\u60c5\u51b5\u65f6\uff0c\u4e5f\u4f1a\u5728\u8003\u8651\u6269\u5c55\u9700\u6c42\u7684\u524d\u63d0\u4e0b\u8c28\u614e\u7ba1\u7406\u8be5\u53d8\u66f4\u3002\u8fd9\u7c7b\u53d8\u66f4\u540c\u6837\u4f1a\u8bb0\u5f55\u5728\u53d1\u5e03\u8bf4\u660e\uff08<a class=\"xref\" href=\"/docs/18/release.html\" title=\"\u9644\u5f55\u00a0E.\u00a0\u53d1\u5e03\u8bf4\u660e\">\u9644\u5f55\u00a0E</a>\uff09\u4e2d\u3002</p>\n<p lang=\"zh\">\u4f46\u8bf7\u6ce8\u610f\uff0c\u670d\u52a1\u5668\u4e2d\u6709\u5f88\u591a\u90e8\u5206\u5e76\u4e0d\u662f\u4f5c\u4e3a\u53ef\u516c\u5f00\u4f7f\u7528\u7684 API \u6765\u8bbe\u8ba1\u548c\u7ef4\u62a4\u7684\uff08\u800c\u4e14\u5728\u5927\u591a\u6570\u60c5\u51b5\u4e0b\uff0c\u5176\u771f\u5b9e\u8fb9\u754c\u4e5f\u5e76\u4e0d\u6e05\u6670\uff09\u3002\u5982\u679c\u51fa\u73b0\u7d27\u6025\u9700\u6c42\uff0c\u5bf9\u8fd9\u4e9b\u90e8\u5206\u8fdb\u884c\u4fee\u6539\u65f6\uff0c\u81ea\u7136\u4f1a\u6bd4\u4fee\u6539\u90a3\u4e9b\u8fb9\u754c\u6e05\u695a\u4e14\u5e7f\u6cdb\u4f7f\u7528\u7684\u63a5\u53e3\u65f6\u66f4\u5c11\u8003\u8651\u6269\u5c55\u4ee3\u7801\u7684\u517c\u5bb9\u6027\u3002</p>\n<p lang=\"zh\">\u6b64\u5916\uff0c\u5728\u7f3a\u4e4f\u81ea\u52a8\u5316\u68c0\u6d4b\u8fd9\u7c7b\u53d8\u5316\u7684\u673a\u5236\u65f6\uff0c\u8fd9\u5e76\u4e0d\u80fd\u6784\u6210\u4e25\u683c\u4fdd\u8bc1\uff1b\u4e0d\u8fc7\u4ece\u5386\u53f2\u4e0a\u770b\uff0c\u8fd9\u79cd\u7834\u574f\u6027\u53d8\u5316\u6781\u4e3a\u7f55\u89c1\u3002</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-COMPOSITE-TYPE-ARGS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-COMPOSITE-TYPE-ARGS\">36.10.7. \u590d\u5408\u7c7b\u578b\u53c2\u6570</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u590d\u5408\u7c7b\u578b\u6ca1\u6709\u50cf C \u7ed3\u6784\u4f53\u90a3\u6837\u7684\u56fa\u5b9a\u5e03\u5c40\u3002\u590d\u5408\u7c7b\u578b\u7684\u5b9e\u4f8b\u53ef\u80fd\u5305\u542b\u7a7a\u503c\u5b57\u6bb5\u3002\u6b64\u5916\uff0c\u7ee7\u627f\u5c42\u6b21\u4e2d\u7684\u590d\u5408\u7c7b\u578b\u53ef\u80fd\u5177\u6709\u548c\u540c\u4e00\u7ee7\u627f\u5c42\u6b21\u4e2d\u5176\u4ed6\u6210\u5458\u4e0d\u540c\u7684\u5b57\u6bb5\u3002\u56e0\u6b64\uff0c<span class=\"productname\">PostgreSQL</span>\u63d0\u4f9b\u4e86\u51fd\u6570\u63a5\u53e3\u4ee5\u4fbf\u4ece C \u8bbf\u95ee\u590d\u5408\u7c7b\u578b\u7684\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u51fd\u6570\u6765\u56de\u7b54\u67e5\u8be2\uff1a</p>\n<pre class=\"programlisting\">SELECT name, c_overpaid(emp, 1500) AS overpaid\n    FROM emp\n    WHERE name = 'Bill' OR name = 'Sam';\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff0c\u53ef\u4ee5\u5c06 c_overpaid \u5b9a\u4e49\u4e3a\uff1a</p>\n<pre class=\"programlisting\">#include \"postgres.h\"\n#include \"executor/executor.h\"  /* for GetAttributeByName() */\n\nPG_MODULE_MAGIC;\n\nPG_FUNCTION_INFO_V1(c_overpaid);\n\nDatum\nc_overpaid(PG_FUNCTION_ARGS)\n{\n    HeapTupleHeader  t = PG_GETARG_HEAPTUPLEHEADER(0);\n    int32            limit = PG_GETARG_INT32(1);\n    bool isnull;\n    Datum salary;\n\n    salary = GetAttributeByName(t, \"salary\", &amp;isnull);\n    if (isnull)\n        PG_RETURN_BOOL(false);\n    /* Alternatively, we might prefer to do PG_RETURN_NULL() for null salary. */\n\n    PG_RETURN_BOOL(DatumGetInt32(salary) &gt; limit);\n}\n\n</pre>\n<p lang=\"zh\"><code class=\"function\">GetAttributeByName</code> \u662f <span class=\"productname\">PostgreSQL</span> \u7684\u4e00\u4e2a\u7cfb\u7edf\u51fd\u6570\uff0c\u7528\u4e8e\u4ece\u6307\u5b9a\u884c\u4e2d\u53d6\u51fa\u5c5e\u6027\u3002\u5b83\u6709\u4e09\u4e2a\u53c2\u6570\uff1a\u4f20\u5165\u51fd\u6570\u7684 <code class=\"type\">HeapTupleHeader</code> \u7c7b\u578b\u53c2\u6570\u3001\u6240\u9700\u5c5e\u6027\u7684\u540d\u79f0\uff0c\u4ee5\u53ca\u4e00\u4e2a\u7528\u4e8e\u6307\u793a\u8be5\u5c5e\u6027\u662f\u5426\u4e3a null \u7684\u8fd4\u56de\u53c2\u6570\u3002<code class=\"function\">GetAttributeByName</code> \u8fd4\u56de\u4e00\u4e2a <code class=\"type\">Datum</code> \u503c\uff0c\u4f60\u53ef\u4ee5\u7528\u9002\u5f53\u7684 <code class=\"function\">DatumGet<em class=\"replaceable\"><code>XXX</code></em>()</code> \u51fd\u6570\u628a\u5b83\u8f6c\u6362\u4e3a\u6b63\u786e\u7684\u6570\u636e\u7c7b\u578b\u3002\u6ce8\u610f\uff0c\u5982\u679c null \u6807\u5fd7\u88ab\u8bbe\u7f6e\uff0c\u90a3\u4e48\u8fd4\u56de\u503c\u672c\u8eab\u6ca1\u6709\u610f\u4e49\uff1b\u5728\u5c1d\u8bd5\u5bf9\u7ed3\u679c\u505a\u4efb\u4f55\u5904\u7406\u4e4b\u524d\uff0c\u52a1\u5fc5\u5148\u68c0\u67e5\u8fd9\u4e2a null \u6807\u5fd7\u3002</p>\n<p lang=\"zh\">\u4e5f\u6709<code class=\"function\">GetAttributeByNum</code>\u51fd\u6570\uff0c\u5b83\u53ef\u4ee5\u7528\u76ee\u6807\u5c5e\u6027\u7684\u5217\u53f7\u800c\u4e0d\u662f\u5c5e\u6027\u540d\u6765\u9009\u62e9\u76ee\u6807\u5c5e\u6027\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u58f0\u660e SQL \u4e2d\u7684<code class=\"function\">c_overpaid</code>\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'c_overpaid'\n    LANGUAGE C STRICT;\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\u6211\u4eec\u7528\u4e86<code class=\"literal\">STRICT</code>\uff0c\u8fd9\u6837\u6211\u4eec\u4e0d\u9700\u8981\u68c0\u67e5\u8f93\u5165\u53c2\u6570\u662f\u5426\u4e3a NULL\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURNING-ROWS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-RETURNING-ROWS\">36.10.8. \u8fd4\u56de\u884c\uff08\u590d\u5408\u7c7b\u578b\uff09</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8981\u4ece C \u8bed\u8a00\u51fd\u6570\u4e2d\u8fd4\u56de\u4e00\u884c\u6216\u4e00\u4e2a\u590d\u5408\u7c7b\u578b\u503c\uff0c\u53ef\u4ee5\u4f7f\u7528\u4e00\u5957\u7279\u6b8a\u7684 API\uff0c\u5b83\u901a\u8fc7\u4e00\u7ec4\u5b8f\u548c\u51fd\u6570\u9690\u85cf\u4e86\u6784\u9020\u590d\u5408\u6570\u636e\u7c7b\u578b\u65f6\u7684\u5927\u90e8\u5206\u590d\u6742\u6027\u3002\u8981\u4f7f\u7528\u8fd9\u5957 API\uff0c\u6e90\u6587\u4ef6\u4e2d\u5fc5\u987b\u5305\u542b\uff1a</p>\n<pre class=\"programlisting\">#include \"funcapi.h\"\n</pre>\n<p lang=\"zh\">\u6784\u9020\u590d\u5408\u6570\u636e\u503c\uff08\u4e0b\u6587\u7b80\u79f0<span class=\"quote\">\u201c<span class=\"quote\">\u5143\u7ec4</span>\u201d</span>\uff09\u6709\u4e24\u79cd\u65b9\u5f0f\uff1a\u4e00\u79cd\u662f\u4ece Datum \u503c\u6570\u7ec4\u6784\u9020\uff0c\u53e6\u4e00\u79cd\u662f\u4ece C \u5b57\u7b26\u4e32\u6570\u7ec4\u6784\u9020\uff0c\u8fd9\u4e9b\u5b57\u7b26\u4e32\u4f1a\u4f20\u7ed9\u8be5\u5143\u7ec4\u5404\u5217\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u8f6c\u6362\u51fd\u6570\u3002\u65e0\u8bba\u91c7\u7528\u54ea\u79cd\u65b9\u5f0f\uff0c\u9996\u5148\u90fd\u9700\u8981\u83b7\u53d6\u6216\u6784\u9020\u63cf\u8ff0\u8be5\u5143\u7ec4\u7ed3\u6784\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5904\u7406 Datum \u65f6\uff0c\u9700\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">BlessTupleDesc</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">heap_form_tuple</code>\u3002\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u5219\u8981\u628a <code class=\"structname\">TupleDesc</code> \u4f20\u7ed9 <code class=\"function\">TupleDescGetAttInMetadata</code>\uff0c\u7136\u540e\u4e3a\u6bcf\u4e00\u884c\u8c03\u7528 <code class=\"function\">BuildTupleFromCStrings</code>\u3002\u5bf9\u4e8e\u8fd4\u56de\u5143\u7ec4\u96c6\u5408\u7684\u51fd\u6570\uff0c\u8fd9\u4e9b\u51c6\u5907\u6b65\u9aa4\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u51fd\u6570\u65f6\u4e00\u6b21\u6027\u5b8c\u6210\u3002</p>\n<p lang=\"zh\">\u6709\u4e00\u4e9b\u8f85\u52a9\u51fd\u6570\u53ef\u4ee5\u7528\u6765\u8bbe\u7f6e\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\u5728\u5927\u591a\u6570\u8fd4\u56de\u590d\u5408\u503c\u7684\u51fd\u6570\u4e2d\uff0c\u63a8\u8350\u7684\u505a\u6cd5\u662f\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo,\n                                   Oid *resultTypeId,\n                                   TupleDesc *resultTupleDesc)\n</pre>\n<p lang=\"zh\">\u4f20\u5165\u8c03\u7528\u51fd\u6570\u672c\u8eab\u6536\u5230\u7684\u540c\u4e00\u4e2a <code class=\"literal\">fcinfo</code> \u7ed3\u6784\u4f53\uff08\u8fd9\u5f53\u7136\u8981\u6c42\u4f7f\u7528\u7248\u672c 1 \u8c03\u7528\u7ea6\u5b9a\uff09\u3002<code class=\"varname\">resultTypeId</code> \u53ef\u4ee5\u6307\u5b9a\u4e3a <code class=\"literal\">NULL</code>\uff0c\u4e5f\u53ef\u4ee5\u6307\u5b9a\u4e3a\u4e00\u4e2a\u672c\u5730\u53d8\u91cf\u7684\u5730\u5740\uff0c\u7528\u4e8e\u63a5\u6536\u51fd\u6570\u7ed3\u679c\u7c7b\u578b\u7684 OID\u3002<code class=\"varname\">resultTupleDesc</code> \u5e94\u5f53\u662f\u4e00\u4e2a\u672c\u5730 <code class=\"structname\">TupleDesc</code> \u53d8\u91cf\u7684\u5730\u5740\u3002\u68c0\u67e5\u8fd4\u56de\u7ed3\u679c\u662f\u5426\u4e3a <code class=\"literal\">TYPEFUNC_COMPOSITE</code>\uff1b\u5982\u679c\u662f\uff0c<code class=\"varname\">resultTupleDesc</code> \u5c31\u4f1a\u88ab\u586b\u5165\u6240\u9700\u7684 <code class=\"structname\">TupleDesc</code>\u3002\uff08\u5982\u679c\u4e0d\u662f\uff0c\u53ef\u4ee5\u62a5\u544a\u4e00\u4e2a\u7c7b\u4f3c<span class=\"quote\">\u201c<span class=\"quote\">function returning record called in context that cannot accept type record</span>\u201d</span>\u7684\u9519\u8bef\u3002\uff09</p>\n<div class=\"tip\">\n<h3 class=\"title\" lang=\"zh\">\u63d0\u793a</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u80fd\u591f\u89e3\u6790\u4e00\u4e2a\u591a\u6001\u51fd\u6570\u7ed3\u679c\u7684\u5b9e\u9645\u7c7b\u578b\uff0c\u56e0\u6b64\u4e0d\u4ec5\u5728\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u51fd\u6570\u4e2d\uff0c\u5728\u8fd4\u56de\u6807\u91cf\u591a\u6001\u7ed3\u679c\u7684\u51fd\u6570\u4e2d\u5b83\u4e5f\u662f\u975e\u5e38\u6709\u7528\u7684\u3002<code class=\"varname\">resultTypeId</code>\u8f93\u51fa\u4e3b\u8981\u7528\u4e8e\u8fd4\u56de\u591a\u6001\u6807\u91cf\u7684\u51fd\u6570\u3002</p>\n</div>\n<div class=\"note\">\n<h3 class=\"title\" lang=\"zh\">\u6ce8\u610f</h3>\n<p lang=\"zh\"><code class=\"function\">get_call_result_type</code>\u6709\u4e00\u4e2a\u5144\u5f1f <code class=\"function\">get_expr_result_type</code>\uff0c\u5b83\u88ab\u7528\u6765\u89e3\u6790\u88ab\u8868\u793a\u4e3a\u4e00\u68f5\u8868\u8fbe\u5f0f\u6811\u7684\u51fd\u6570\u8c03\u7528\u7684\u8f93\u51fa\u7c7b\u578b\u3002\u5728\u5c1d\u8bd5\u4ece\u51fd\u6570\u81ea\u8eab\u5916\u90e8\u786e\u5b9a\u7ed3\u679c\u7c7b\u578b\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e5f\u6709\u4e00\u4e2a<code class=\"function\">get_func_result_type</code>\uff0c\u5f53\u53ea\u6709\u51fd\u6570\u7684 OID \u53ef\u7528\u65f6\u53ef\u4ee5\u7528\u5b83\u3002\u4e0d\u8fc7\u8fd9\u4e9b\u51fd\u6570\u65e0\u6cd5\u5904\u7406\u88ab\u58f0\u660e\u4e3a\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\uff0c\u5e76\u4e14<code class=\"function\">get_func_result_type</code>\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\uff0c\u56e0\u6b64\u4f60\u5e94\u8be5\u4f18\u5148\u4f7f\u7528<code class=\"function\">get_call_result_type</code>\u3002</p>\n</div>\n<p lang=\"zh\">\u66f4\u65e9\u3001\u73b0\u5728\u5df2\u88ab\u5f03\u7528\u7684\u83b7\u53d6<code class=\"structname\">TupleDesc</code>\u7684\u51fd\u6570\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc RelationNameGetTupleDesc(const char *relname)\n</pre>\n<p lang=\"zh\">\u5b83\u53ef\u4ee5\u4e3a\u4e00\u4e2a\u6307\u5b9a\u540d\u79f0\u7684\u5173\u7cfb\u7684\u884c\u7c7b\u578b\u5f97\u5230<code class=\"structname\">TupleDesc</code>\uff0c\u8fd8\u6709\uff1a</p>\n<pre class=\"programlisting\">TupleDesc TypeGetTupleDesc(Oid typeoid, List *colaliases)\n</pre>\n<p lang=\"zh\">\u53ef\u4ee5\u57fa\u4e8e\u4e00\u4e2a\u7c7b\u578b OID \u5f97\u5230<code class=\"structname\">TupleDesc</code>\u3002\u8fd9\u53ef\u4ee5\u88ab\u7528\u6765\u4e3a\u4e00\u79cd\u57fa\u672c\u6216\u8005\u590d\u5408\u7c7b\u578b\u83b7\u5f97<code class=\"structname\">TupleDesc</code>\u3002\u4e0d\u8fc7\uff0c\u5bf9\u4e8e\u8fd4\u56de<code class=\"structname\">record</code>\u7684\u51fd\u6570\u5b83\u4e0d\u8d77\u4f5c\u7528\uff0c\u5e76\u4e14\u5b83\u65e0\u6cd5\u89e3\u6790\u591a\u6001\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u6709\u4e86\u4e00\u4e2a<code class=\"structname\">TupleDesc</code>\uff0c\u5982\u679c\u8ba1\u5212\u5904\u7406 Datum\uff0c\u53ef\u4ee5\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">TupleDesc BlessTupleDesc(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u8ba1\u5212\u5904\u7406 C \u5b57\u7b26\u4e32\uff0c\u53ef\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">AttInMetadata *TupleDescGetAttInMetadata(TupleDesc tupdesc)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u6b63\u5728\u7f16\u5199\u4e00\u4e2a\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u4f60\u53ef\u4ee5\u628a\u8fd9\u4e9b\u51fd\u6570\u7684\u7ed3\u679c\u4fdd\u5b58\u5728 <code class=\"structname\">FuncCallContext</code>\u7ed3\u6784\u4f53\u4e2d \u2014 \u5206\u522b\u4f7f\u7528 <code class=\"structfield\">tuple_desc</code>\u6216\u8005<code class=\"structfield\">attinmeta</code>\u5b57\u6bb5\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 Datum \u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple heap_form_tuple(TupleDesc tupdesc, Datum *values, bool *isnull)\n</pre>\n<p lang=\"zh\">\u6765\u7528 Datum \u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002</p>\n<p lang=\"zh\">\u5728\u5904\u7406 C \u5b57\u7b26\u4e32\u65f6\uff0c\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTuple BuildTupleFromCStrings(AttInMetadata *attinmeta, char **values)\n</pre>\n<p lang=\"zh\">\u6765\u7528 C \u5b57\u7b26\u4e32\u5f62\u5f0f\u7684\u7528\u6237\u6570\u636e\u6784\u5efa\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u3002<em class=\"parameter\"><code>values</code></em>\u662f\u4e00\u4e2a C \u5b57\u7b26\u4e32\u6570\u7ec4\uff0c\u6bcf\u4e00\u4e2a\u5143\u7d20\u662f\u8fd4\u56de\u884c\u7684\u4e00\u4e2a\u5c5e\u6027\u3002\u6bcf\u4e00\u4e2a C \u5b57\u7b26\u4e32\u5e94\u8be5\u662f\u8be5\u5c5e\u6027\u6570\u636e\u7c7b\u578b\u7684\u8f93\u5165\u51fd\u6570\u6240\u671f\u671b\u7684\u683c\u5f0f\u3002\u4e3a\u4e86\u5bf9\u4e00\u4e2a\u5c5e\u6027\u8fd4\u56de\u7a7a\u503c\uff0c<em class=\"parameter\"><code>values</code></em>\u6570\u7ec4\u4e2d\u5bf9\u5e94\u7684\u6307\u9488\u5e94\u8be5\u88ab\u8bbe\u7f6e\u4e3a<code class=\"symbol\">NULL</code>\u3002\u5bf9\u4e8e\u4f60\u8fd4\u56de\u7684\u6bcf\u4e00\u884c\u90fd\u9700\u8981\u518d\u6b21\u8c03\u7528\u8fd9\u4e2a\u51fd\u6570\u3002</p>\n<p lang=\"zh\">\u4e00\u65e6\u5df2\u7ecf\u6784\u5efa\u4e86\u4e00\u4e2a\u8981\u4ece\u51fd\u6570\u4e2d\u8fd4\u56de\u7684\u5143\u7ec4\uff0c\u5b83\u5fc5\u987b\u88ab\u8f6c\u6362\u6210\u4e00\u4e2a <code class=\"type\">Datum</code>\u3002\u4f7f\u7528</p>\n<pre class=\"programlisting\">HeapTupleGetDatum(HeapTuple tuple)\n</pre>\n<p lang=\"zh\">\u53ef\u628a\u4e00\u4e2a<code class=\"structname\">HeapTuple</code>\u8f6c\u6362\u6210\u5408\u6cd5\u7684 Datum\u3002\u5982\u679c\u4f60\u53ea\u60f3\u8fd4\u56de\u4e00\u884c\uff0c\u90a3\u4e48\u8fd9\u4e2a<code class=\"type\">Datum</code>\u53ef\u4ee5\u88ab\u76f4\u63a5\u8fd4\u56de\uff0c\u5728\u4e00\u4e2a\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u4e2d\u5b83\u4e5f\u53ef\u4ee5\u88ab\u5f53\u505a\u5f53\u524d\u7684\u8fd4\u56de\u503c\u3002</p>\n<p lang=\"zh\">\u4e0b\u4e00\u8282\u4e2d\u4f1a\u6709\u4e00\u4e2a\u793a\u4f8b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-RETURN-SET\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-RETURN-SET\">36.10.9. \u8fd4\u56de\u96c6\u5408</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">C \u8bed\u8a00\u51fd\u6570\u6709\u4e24\u79cd\u8fd4\u56de\u96c6\u5408\uff08\u591a\u884c\uff09\u7684\u65b9\u6cd5\u3002\u7b2c\u4e00\u79cd\u79f0\u4e3a ValuePerCall \u6a21\u5f0f\uff1a\u53cd\u590d\u8c03\u7528\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff0c\u6bcf\u6b21\u4f20\u5165\u76f8\u540c\u53c2\u6570\uff0c\u6bcf\u6b21\u8fd4\u56de\u4e00\u884c\u65b0\u6570\u636e\uff0c\u76f4\u5230\u6ca1\u6709\u66f4\u591a\u884c\uff0c\u5e76\u4ee5\u8fd4\u56de NULL \u8868\u793a\u7ed3\u675f\u3002\u56e0\u6b64\uff0c\u8fd4\u56de\u96c6\u5408\u7684\u51fd\u6570\uff08SRF\uff09\u5fc5\u987b\u8de8\u8c03\u7528\u4fdd\u5b58\u8db3\u591f\u7684\u72b6\u6001\uff0c\u8bb0\u5f55\u6267\u884c\u8fdb\u5ea6\uff0c\u786e\u4fdd\u6bcf\u6b21\u8c03\u7528\u8fd4\u56de\u6b63\u786e\u7684\u4e0b\u4e00\u9879\u3002\u7b2c\u4e8c\u79cd\u79f0\u4e3a Materialize \u6a21\u5f0f\uff1aSRF \u586b\u5145\u5e76\u8fd4\u56de\u4e00\u4e2a\u5305\u542b\u5168\u90e8\u7ed3\u679c\u7684 tuplestore \u5bf9\u8c61\u3002\u6574\u4e2a\u7ed3\u679c\u53ea\u9700\u8c03\u7528\u4e00\u6b21\uff0c\u56e0\u6b64\u65e0\u9700\u4fdd\u5b58\u8c03\u7528\u4e4b\u95f4\u7684\u72b6\u6001\u3002</p>\n<p lang=\"zh\">\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u65f6\uff0c\u91cd\u8981\u7684\u662f\u8981\u8bb0\u4f4f\u67e5\u8be2\u4e0d\u80fd\u4fdd\u8bc1\u8fd0\u884c\u5b8c\u6210\uff1b\u4e5f\u5c31\u662f\u8bf4\uff0c\u7531\u4e8e\u8bf8\u5982<code class=\"literal\">LIMIT</code>\u4e4b\u7c7b\u7684\u9009\u9879\uff0c\u6267\u884c\u5668\u53ef\u80fd\u4f1a\u5728\u83b7\u53d6\u6240\u6709\u884c\u4e4b\u524d\u505c\u6b62\u8c03\u7528\u96c6\u5408\u8fd4\u56de\u51fd\u6570\u3002\u8fd9\u610f\u5473\u7740\u5728\u6700\u540e\u4e00\u6b21\u8c03\u7528\u4e2d\u6267\u884c\u6e05\u7406\u6d3b\u52a8\u662f\u4e0d\u5b89\u5168\u7684\uff0c\u56e0\u4e3a\u8fd9\u53ef\u80fd\u6c38\u8fdc\u4e0d\u4f1a\u53d1\u751f\u3002\u5bf9\u4e8e\u9700\u8981\u8bbf\u95ee\u5916\u90e8\u8d44\u6e90\uff08\u4f8b\u5982\u6587\u4ef6\u63cf\u8ff0\u7b26\uff09\u7684\u51fd\u6570\uff0c\u5efa\u8bae\u4f7f\u7528 Materialize \u6a21\u5f0f\u3002</p>\n<p lang=\"zh\">\u672c\u8282\u7684\u5176\u4f59\u90e8\u5206\u8bb0\u5f55\u4e86\u4e00\u7ec4\u4f7f\u7528 ValuePerCall \u6a21\u5f0f\u7684 SRF \u5e38\u7528\uff08\u5c3d\u7ba1\u4e0d\u662f\u5fc5\u987b\u4f7f\u7528\uff09\u7684\u8f85\u52a9\u5b8f\u3002\u6709\u5173 Materialize \u6a21\u5f0f\u7684\u5176\u4ed6\u8be6\u7ec6\u4fe1\u606f\u53ef\u4ee5\u5728<code class=\"filename\">src/backend/utils/fmgr/README</code>\u4e2d\u627e\u5230\u3002\u6b64\u5916\uff0c<span class=\"productname\">PostgreSQL</span>\u6e90\u4ee3\u7801\u5206\u53d1\u4e2d\u7684<code class=\"filename\">contrib</code> \u6a21\u5757\u5305\u542b\u8bb8\u591a\u4f7f\u7528 ValuePerCall \u548c Materialize \u6a21\u5f0f\u7684 SRF \u793a\u4f8b\u3002</p>\n<p lang=\"zh\">\u8981\u4f7f\u7528\u6b64\u5904\u63cf\u8ff0\u7684 ValuePerCall \u652f\u6301\u5b8f\uff0c\u8bf7\u5305\u542b<code class=\"filename\">funcapi.h</code>\u3002\u8fd9\u4e9b\u5b8f\u4e0e\u7ed3\u6784\u4f53<code class=\"structname\">FuncCallContext</code>\u4e00\u8d77\u4f7f\u7528\uff0c\u8be5\u7ed3\u6784\u4f53\u5305\u542b\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u5b58\u7684\u72b6\u6001\u3002\u5728\u4f7f\u7528\u8fd9\u4e9b\u5b8f\u7684 SRF \u4e2d\uff0c<code class=\"literal\">fcinfo-&gt;flinfo-&gt;fn_extra</code>\u7528\u4e8e\u5728\u8c03\u7528\u4e4b\u95f4\u4fdd\u5b58\u6307\u5411<code class=\"structname\">FuncCallContext</code>\u7684\u6307\u9488\u3002\u5b8f\u5728\u7b2c\u4e00\u6b21\u4f7f\u7528\u65f6\u81ea\u52a8\u586b\u5145\u8be5\u5b57\u6bb5\uff0c\u5e76\u671f\u671b\u5728\u540e\u7eed\u4f7f\u7528\u4e2d\u627e\u5230\u76f8\u540c\u7684\u6307\u9488\u3002</p>\n<pre class=\"programlisting\">typedef struct FuncCallContext\n{\n    /*\n     * Number of times we've been called before\n     *\n     * call_cntr is initialized to 0 for you by SRF_FIRSTCALL_INIT(), and\n     * incremented for you every time SRF_RETURN_NEXT() is called.\n     */\n    uint64 call_cntr;\n\n    /*\n     * OPTIONAL maximum number of calls\n     *\n     * max_calls is here for convenience only and setting it is optional.\n     * If not set, you must provide alternative means to know when the\n     * function is done.\n     */\n    uint64 max_calls;\n\n    /*\n     * OPTIONAL pointer to miscellaneous user-provided context information\n     *\n     * user_fctx is for use as a pointer to your own data to retain\n     * arbitrary context information between calls of your function.\n     */\n    void *user_fctx;\n\n    /*\n     * OPTIONAL pointer to struct containing attribute type input metadata\n     *\n     * attinmeta is for use when returning tuples (i.e., composite data types)\n     * and is not used when returning base data types. It is only needed\n     * if you intend to use BuildTupleFromCStrings() to create the return\n     * tuple.\n     */\n    AttInMetadata *attinmeta;\n\n    /*\n     * memory context used for structures that must live for multiple calls\n     *\n     * multi_call_memory_ctx is set by SRF_FIRSTCALL_INIT() for you, and used\n     * by SRF_RETURN_DONE() for cleanup. It is the most appropriate memory\n     * context for any memory that is to be reused across multiple calls\n     * of the SRF.\n     */\n    MemoryContext multi_call_memory_ctx;\n\n    /*\n     * OPTIONAL pointer to struct containing tuple description\n     *\n     * tuple_desc is for use when returning tuples (i.e., composite data types)\n     * and is only needed if you are going to build the tuples with\n     * heap_form_tuple() rather than with BuildTupleFromCStrings().  Note that\n     * the TupleDesc pointer stored here should usually have been run through\n     * BlessTupleDesc() first.\n     */\n    TupleDesc tuple_desc;\n\n} FuncCallContext;\n</pre>\n<p lang=\"zh\">\u4f7f\u7528\u6b64\u57fa\u7840\u7ed3\u6784\u7684<acronym class=\"acronym\">SRF</acronym>\u5c06\u4f7f\u7528\u7684\u5b8f\u662f\uff1a</p>\n<pre class=\"programlisting\">SRF_IS_FIRSTCALL()\n</pre>\n<p lang=\"zh\">\u6765\u5224\u65ad\u4f60\u7684\u51fd\u6570\u662f\u5426\u662f\u7b2c\u4e00\u6b21\u88ab\u8c03\u7528\u3002\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff08\u53ea\u80fd\u5728\u7b2c\u4e00\u6b21\u8c03\u7528\u65f6\uff09\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_FIRSTCALL_INIT()\n</pre>\n<p lang=\"zh\">\u521d\u59cb\u5316<code class=\"structname\">FuncCallContext</code>\u3002\u5728\u6bcf\u6b21\u51fd\u6570\u8c03\u7528\u65f6\uff0c\u5305\u542b\u7b2c\u4e00\u6b21\uff0c\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_PERCALL_SETUP()\n</pre>\n<p lang=\"zh\">\u8bbe\u7f6e\u4f7f\u7528<code class=\"structname\">FuncCallContext</code>\u3002</p>\n<p lang=\"zh\">\u5982\u679c\u4f60\u7684\u51fd\u6570\u5728\u5f53\u524d\u8c03\u7528\u4e2d\u6709\u6570\u636e\u8981\u8fd4\u56de\uff0c\u8bf7\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_NEXT(funcctx, result)\n</pre>\n<p lang=\"zh\">\u628a\u5b83\u8fd4\u56de\u7ed9\u8c03\u7528\u8005\uff08<code class=\"literal\">result</code>\u5fc5\u987b\u662f\u7c7b\u578b<code class=\"type\">Datum</code>\uff0c\u53ef\u4ee5\u662f\u4e00\u4e2a\u5355\u4e00\u503c\u6216\u8005\u6309\u4e0a\u6587\u6240\u8ff0\u51c6\u5907\u597d\u7684\u5143\u7ec4\uff09\u3002\u6700\u540e\uff0c\u5f53\u51fd\u6570\u5b8c\u6210\u4e86\u6570\u636e\u8fd4\u56de\u540e\uff0c\u53ef\u4f7f\u7528\uff1a</p>\n<pre class=\"programlisting\">SRF_RETURN_DONE(funcctx)\n</pre>\n<p lang=\"zh\">\u7528\u4e8e\u6e05\u7406\u5e76\u7ed3\u675f SRF\u3002</p>\n<p lang=\"zh\">\u8c03\u7528 SRF \u65f6\u7684\u5f53\u524d\u5185\u5b58\u4e0a\u4e0b\u6587\u662f\u4e34\u65f6\u4e0a\u4e0b\u6587\uff0c\u4f1a\u5728\u4e24\u6b21\u8c03\u7528\u4e4b\u95f4\u6e05\u7a7a\u3002\u56e0\u6b64\uff0c\u65e0\u9700\u5bf9\u901a\u8fc7 palloc \u5206\u914d\u7684\u6bcf\u5757\u5185\u5b58\u8c03\u7528 pfree\uff0c\u5b83\u4eec\u90fd\u4f1a\u88ab\u81ea\u52a8\u6e05\u7406\u3002\u4e0d\u8fc7\uff0c\u9700\u8981\u8de8\u8c03\u7528\u4fdd\u7559\u7684\u6570\u636e\u7ed3\u6784\u5fc5\u987b\u653e\u5728\u5176\u4ed6\u4f4d\u7f6e\u3002multi_call_memory_ctx \u6240\u5f15\u7528\u7684\u5185\u5b58\u4e0a\u4e0b\u6587\u9002\u5408\u4fdd\u5b58\u76f4\u5230 SRF \u8fd0\u884c\u7ed3\u675f\u4ecd\u9700\u4fdd\u7559\u7684\u6570\u636e\u3002\u901a\u5e38\u5e94\u5728\u9996\u6b21\u8c03\u7528\u7684\u521d\u59cb\u5316\u9636\u6bb5\u5207\u6362\u5230 multi_call_memory_ctx\uff0c\u5e76\u7528 funcctx-&gt;user_fctx \u4fdd\u5b58\u6307\u5411\u6b64\u7c7b\u8de8\u8c03\u7528\u6570\u636e\u7ed3\u6784\u7684\u6307\u9488\u3002\uff08\u5728 multi_call_memory_ctx \u4e2d\u5206\u914d\u7684\u6570\u636e\u4f1a\u5728\u67e5\u8be2\u7ed3\u675f\u65f6\u81ea\u52a8\u6e05\u7406\uff0c\u4e5f\u65e0\u9700\u624b\u52a8\u91ca\u653e\u3002\uff09</p>\n<div class=\"warning\">\n<h3 class=\"title\" lang=\"zh\">\u8b66\u544a</h3>\n<p lang=\"zh\">\u867d\u7136\u51fd\u6570\u7684\u5b9e\u53c2\u5728\u591a\u6b21\u8c03\u7528\u4e4b\u95f4\u4fdd\u6301\u4e0d\u53d8\uff0c\u4f46\u5982\u679c\u5728\u77ac\u65f6\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u4e86\u53c2\u6570\uff08\u901a\u5e38\u7531 <code class=\"function\">PG_GETARG_<em class=\"replaceable\"><code>xxx</code></em></code> \u5b8f\u5b8c\u6210\uff09\uff0c\u90a3\u4e48\u88ab\u53cd TOAST \u7684\u62f7\u8d1d\u5c06\u5728\u6bcf\u6b21\u5faa\u73af\u4e2d\u88ab\u91ca\u653e\u3002\u76f8\u5e94\u5730\uff0c\u5982\u679c\u4f60\u628a\u8fd9\u4e9b\u503c\u7684\u5f15\u7528\u4fdd\u5b58\u5728<code class=\"structfield\">user_fctx</code>\u4e2d\uff0c\u4f60\u4e5f\u5fc5\u987b\u5728\u53cd TOAST \u4e4b\u540e\u628a\u5b83\u4eec\u62f7\u8d1d\u5230 <code class=\"structfield\">multi_call_memory_ctx</code>\u4e2d\uff0c\u6216\u8005\u786e\u4fdd\u4f60\u53ea\u5728\u90a3\u4e2a\u4e0a\u4e0b\u6587\u4e2d\u53cd TOAST \u8fd9\u4e9b\u503c\u3002</p>\n</div>\n<p lang=\"zh\">\u4e00\u4e2a\u5b8c\u6574\u7684\u4f2a\u4ee3\u7801\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">Datum\nmy_set_returning_function(PG_FUNCTION_ARGS)\n{\n    FuncCallContext  *funcctx;\n    Datum             result;\n    <em class=\"replaceable\"><code>further declarations as needed</code></em>\n\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext oldcontext;\n\n        funcctx = SRF_FIRSTCALL_INIT();\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n        /* One-time setup code appears here: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>if returning composite</code></em>\n            <em class=\"replaceable\"><code>build TupleDesc, and perhaps AttInMetadata</code></em>\n        <em class=\"replaceable\"><code>endif returning composite</code></em>\n        <em class=\"replaceable\"><code>user code</code></em>\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* Each-time setup code appears here: */\n    <em class=\"replaceable\"><code>user code</code></em>\n    funcctx = SRF_PERCALL_SETUP();\n    <em class=\"replaceable\"><code>user code</code></em>\n\n    /* this is just one way we might test whether we are done: */\n    if (funcctx-&gt;call_cntr &lt; funcctx-&gt;max_calls)\n    {\n        /* Here we want to return another item: */\n        <em class=\"replaceable\"><code>user code</code></em>\n        <em class=\"replaceable\"><code>obtain result Datum</code></em>\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else\n    {\n        /* Here we are done returning items, so just report that fact. */\n        /* (Resist the temptation to put cleanup code here.) */\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n</pre>\n<p lang=\"zh\">\u4e00\u4e2a\u8fd4\u56de\u590d\u5408\u7c7b\u578b\u7684\u7b80\u5355<acronym class=\"acronym\">SRF</acronym>\u7684\u5b8c\u6574\u793a\u4f8b\u5982\u4e0b\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(retcomposite);\n\nDatum\nretcomposite(PG_FUNCTION_ARGS)\n{\n    FuncCallContext     *funcctx;\n    int                  call_cntr;\n    int                  max_calls;\n    TupleDesc            tupdesc;\n    AttInMetadata       *attinmeta;\n\n    /* stuff done only on the first call of the function */\n    if (SRF_IS_FIRSTCALL())\n    {\n        MemoryContext   oldcontext;\n\n        /* create a function context for cross-call persistence */\n        funcctx = SRF_FIRSTCALL_INIT();\n\n        /* switch to memory context appropriate for multiple function calls */\n        oldcontext = MemoryContextSwitchTo(funcctx-&gt;multi_call_memory_ctx);\n\n        /* total number of tuples to be returned */\n        funcctx-&gt;max_calls = PG_GETARG_INT32(0);\n\n        /* Build a tuple descriptor for our result type */\n        if (get_call_result_type(fcinfo, NULL, &amp;tupdesc) != TYPEFUNC_COMPOSITE)\n            ereport(ERROR,\n                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),\n                     errmsg(\"function returning record called in context \"\n                            \"that cannot accept type record\")));\n\n        /*\n         * generate attribute metadata needed later to produce tuples from raw\n         * C strings\n         */\n        attinmeta = TupleDescGetAttInMetadata(tupdesc);\n        funcctx-&gt;attinmeta = attinmeta;\n\n        MemoryContextSwitchTo(oldcontext);\n    }\n\n    /* stuff done on every call of the function */\n    funcctx = SRF_PERCALL_SETUP();\n\n    call_cntr = funcctx-&gt;call_cntr;\n    max_calls = funcctx-&gt;max_calls;\n    attinmeta = funcctx-&gt;attinmeta;\n\n    if (call_cntr &lt; max_calls)    /* do when there is more left to send */\n    {\n        char       **values;\n        HeapTuple    tuple;\n        Datum        result;\n\n        /*\n         * Prepare a values array for building the returned tuple.\n         * This should be an array of C strings which will\n         * be processed later by the type input functions.\n         */\n        values = (char **) palloc(3 * sizeof(char *));\n        values[0] = (char *) palloc(16 * sizeof(char));\n        values[1] = (char *) palloc(16 * sizeof(char));\n        values[2] = (char *) palloc(16 * sizeof(char));\n\n        snprintf(values[0], 16, \"%d\", 1 * PG_GETARG_INT32(1));\n        snprintf(values[1], 16, \"%d\", 2 * PG_GETARG_INT32(1));\n        snprintf(values[2], 16, \"%d\", 3 * PG_GETARG_INT32(1));\n\n        /* build a tuple */\n        tuple = BuildTupleFromCStrings(attinmeta, values);\n\n        /* make the tuple into a datum */\n        result = HeapTupleGetDatum(tuple);\n\n        /* clean up (this is not really necessary) */\n        pfree(values[0]);\n        pfree(values[1]);\n        pfree(values[2]);\n        pfree(values);\n\n        SRF_RETURN_NEXT(funcctx, result);\n    }\n    else    /* do when there is no more left */\n    {\n        SRF_RETURN_DONE(funcctx);\n    }\n}\n\n</pre>\n<p lang=\"zh\">\u5728SQL\u4e2d\u58f0\u660e\u6b64\u51fd\u6570\u7684\u4e00\u79cd\u65b9\u6cd5\u662f\uff1a</p>\n<pre class=\"programlisting\">CREATE TYPE __retcomposite AS (f1 integer, f2 integer, f3 integer);\n\nCREATE OR REPLACE FUNCTION retcomposite(integer, integer)\n    RETURNS SETOF __retcomposite\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u65b9\u6cd5\u662f\u4f7f\u7528OUT\u53c2\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE OR REPLACE FUNCTION retcomposite(IN integer, IN integer,\n    OUT f1 integer, OUT f2 integer, OUT f3 integer)\n    RETURNS SETOF record\n    AS '<em class=\"replaceable\"><code>filename</code></em>', 'retcomposite'\n    LANGUAGE C IMMUTABLE STRICT;\n</pre>\n<p lang=\"zh\">\u8bf7\u6ce8\u610f\uff0c\u91c7\u7528\u8fd9\u79cd\u65b9\u6cd5\u65f6\uff0c\u51fd\u6570\u7684\u8f93\u51fa\u7c7b\u578b\u5728\u5f62\u5f0f\u4e0a\u662f\u4e00\u4e2a\u533f\u540d\u7684 <code class=\"structname\">record</code> \u7c7b\u578b\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-C-POLYMORPHIC\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-C-POLYMORPHIC\">36.10.10. \u591a\u6001\u53c2\u6570\u548c\u8fd4\u56de\u7c7b\u578b</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u53ef\u4ee5\u58f0\u660e C \u8bed\u8a00\u51fd\u6570\u6765\u63a5\u53d7\u548c\u8fd4\u56de<a class=\"xref\" href=\"/docs/18/extend-type-system.html#EXTEND-TYPES-POLYMORPHIC\" title=\"36.2.5.\u00a0\u591a\u6001\u7c7b\u578b\">\u7b2c\u00a036.2.5\u00a0\u8282</a>\u4e2d\u63cf\u8ff0\u7684\u591a\u6001\u7c7b\u578b\u3002\u5f53\u51fd\u6570\u53c2\u6570\u6216\u8005\u8fd4\u56de\u7c7b\u578b\u88ab\u5b9a\u4e49\u4e3a\u591a\u6001\u7c7b\u578b\u65f6\uff0c\u51fd\u6570\u7684\u7f16\u5199\u8005\u65e0\u6cd5\u63d0\u524d\u77e5\u9053\u4f1a\u7528\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u8c03\u7528\u8be5\u51fd\u6570\u6216\u8005\u8be5\u51fd\u6570\u9700\u8981\u8fd4\u56de\u4ec0\u4e48\u6570\u636e\u7c7b\u578b\u3002\u5728<code class=\"filename\">fmgr.h</code> \u4e2d\u63d0\u4f9b\u4e86\u4e24\u79cd\u4f8b\u7a0b\u6765\u5141\u8bb8\u7248\u672c-1 \u7684 C \u51fd\u6570\u53d1\u73b0\u5176\u53c2\u6570\u7684\u5b9e\u9645\u6570\u636e\u7c7b\u578b\u4ee5\u53ca\u5b83\u8981\u8fd4\u56de\u7684\u7c7b\u578b\u3002\u8fd9\u4e9b\u4f8b\u7a0b\u88ab\u79f0\u4e3a <code class=\"literal\">get_fn_expr_rettype(FmgrInfo *flinfo)</code>\u548c <code class=\"literal\">get_fn_expr_argtype(FmgrInfo *flinfo, int argnum)</code>\u3002\u5b83\u4eec\u8fd4\u56de\u7ed3\u679c\u6216\u8005\u53c2\u6570\u7684\u7c7b\u578b\u7684 OID\uff0c\u6216\u8005\u5f53\u8be5\u4fe1\u606f\u4e0d\u53ef\u7528\u65f6\u8fd4\u56de <code class=\"symbol\">InvalidOid</code>\u3002\u7ed3\u6784\u4f53<code class=\"literal\">flinfo</code>\u901a\u5e38\u88ab\u5f53\u505a <code class=\"literal\">fcinfo-&gt;flinfo</code>\u8bbf\u95ee\u3002\u53c2\u6570<code class=\"literal\">argnum</code>\u5219\u662f\u4ece\u96f6\u5f00\u59cb\u8ba1\u3002<code class=\"function\">get_call_result_type</code>\u4e5f\u53ef\u88ab\u7528\u4f5c <code class=\"function\">get_fn_expr_rettype</code>\u7684\u4e00\u79cd\u66ff\u4ee3\u54c1\u3002\u8fd8\u6709 <code class=\"function\">get_fn_expr_variadic</code>\uff0c\u5b83\u53ef\u4ee5\u88ab\u7528\u6765\u627e\u51fa\u53ef\u53d8\u53c2\u6570\u662f\u5426\u5df2\u7ecf\u88ab\u5408\u5e76\u5230\u4e86\u4e00\u4e2a\u6570\u7ec4\u4e2d\u3002\u8fd9\u4e3b\u8981\u7528\u4e8e <code class=\"literal\">VARIADIC \"any\"</code>\u51fd\u6570\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u63a5\u6536\u666e\u901a\u6570\u7ec4\u7c7b\u578b\u7684\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u6765\u8bf4\u603b\u662f\u4f1a\u53d1\u751f\u8fd9\u7c7b\u5408\u5e76\u3002</p>\n<p lang=\"zh\">\u4f8b\u5982\uff0c\u5047\u8bbe\u6211\u4eec\u60f3\u8981\u5199\u4e00\u4e2a\u63a5\u6536\u4e00\u4e2a\u4efb\u610f\u7c7b\u578b\u5143\u7d20\u5e76\u4e14\u8fd4\u56de\u4e00\u4e2a\u8be5\u7c7b\u578b\u7684\u4e00\u7ef4\u6570\u7ec4\u7684\u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">PG_FUNCTION_INFO_V1(make_array);\nDatum\nmake_array(PG_FUNCTION_ARGS)\n{\n    ArrayType  *result;\n    Oid         element_type = get_fn_expr_argtype(fcinfo-&gt;flinfo, 0);\n    Datum       element;\n    bool        isnull;\n    int16       typlen;\n    bool        typbyval;\n    char        typalign;\n    int         ndims;\n    int         dims[MAXDIM];\n    int         lbs[MAXDIM];\n\n    if (!OidIsValid(element_type))\n        elog(ERROR, \"could not determine data type of input\");\n\n    /* get the provided element, being careful in case it's NULL */\n    isnull = PG_ARGISNULL(0);\n    if (isnull)\n        element = (Datum) 0;\n    else\n        element = PG_GETARG_DATUM(0);\n\n    /* we have one dimension */\n    ndims = 1;\n    /* and one element */\n    dims[0] = 1;\n    /* and lower bound is 1 */\n    lbs[0] = 1;\n\n    /* get required info about the element type */\n    get_typlenbyvalalign(element_type, &amp;typlen, &amp;typbyval, &amp;typalign);\n\n    /* now build the array */\n    result = construct_md_array(&amp;element, &amp;isnull, ndims, dims, lbs,\n                                element_type, typlen, typbyval, typalign);\n\n    PG_RETURN_ARRAYTYPE_P(result);\n}\n</pre>\n<p lang=\"zh\">\u4e0b\u9762\u7684\u547d\u4ee4\u5728 SQL \u4e2d\u58f0\u660e\u4e86 <code class=\"function\">make_array</code> \u51fd\u6570\uff1a</p>\n<pre class=\"programlisting\">CREATE FUNCTION make_array(anyelement) RETURNS anyarray\n    AS '<em class=\"replaceable\"><code>DIRECTORY</code></em>/funcs', 'make_array'\n    LANGUAGE C IMMUTABLE;\n</pre>\n<p lang=\"zh\">\u8fd8\u6709\u4e00\u79cd\u53ea\u5bf9 C \u8bed\u8a00\u51fd\u6570\u53ef\u7528\u7684\u591a\u6001\u53d8\u4f53\uff1a\u5b83\u4eec\u53ef\u4ee5\u88ab\u58f0\u660e\u4e3a\u63a5\u53d7 <code class=\"literal\">\"any\"</code> \u7c7b\u578b\u7684\u53c2\u6570\u3002\uff08\u6ce8\u610f\uff0c\u8fd9\u4e2a\u7c7b\u578b\u540d\u5fc5\u987b\u7528\u53cc\u5f15\u53f7\u62ec\u8d77\u6765\uff0c\u56e0\u4e3a\u5b83\u540c\u65f6\u4e5f\u662f SQL \u4fdd\u7559\u5b57\u3002\uff09\u5b83\u4e0e <code class=\"type\">anyelement</code> \u7c7b\u4f3c\uff0c\u4f46\u4e0d\u4f1a\u8981\u6c42\u4e0d\u540c\u7684 <code class=\"literal\">\"any\"</code> \u53c2\u6570\u5fc5\u987b\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff0c\u4e5f\u4e0d\u4f1a\u5e2e\u52a9\u786e\u5b9a\u51fd\u6570\u7684\u7ed3\u679c\u7c7b\u578b\u3002C \u8bed\u8a00\u51fd\u6570\u8fd8\u53ef\u4ee5\u628a\u6700\u540e\u4e00\u4e2a\u53c2\u6570\u58f0\u660e\u4e3a <code class=\"literal\">VARIADIC \"any\"</code>\u3002\u8fd9\u53ef\u4ee5\u5339\u914d\u4e00\u4e2a\u6216\u591a\u4e2a\u4efb\u610f\u7c7b\u578b\u7684\u5b9e\u53c2\uff08\u4e0d\u5fc5\u662f\u540c\u4e00\u79cd\u7c7b\u578b\uff09\u3002\u8fd9\u4e9b\u53c2\u6570<span class=\"emphasis\"><em>\u4e0d\u4f1a</em></span>\u50cf\u666e\u901a\u53ef\u53d8\u53c2\u6570\u51fd\u6570\u90a3\u6837\u88ab\u6536\u96c6\u6210\u4e00\u4e2a\u6570\u7ec4\uff0c\u800c\u662f\u4f1a\u5355\u72ec\u4f20\u7ed9\u51fd\u6570\u3002\u4f7f\u7528\u8fd9\u79cd\u7279\u6027\u65f6\uff0c\u5fc5\u987b\u7ed3\u5408 <code class=\"function\">PG_NARGS()</code> \u5b8f\u4ee5\u53ca\u524d\u9762\u4ecb\u7ecd\u7684\u65b9\u6cd5\u6765\u786e\u5b9a\u5b9e\u53c2\u7684\u4e2a\u6570\u548c\u7c7b\u578b\u3002\u6b64\u5916\uff0c\u8fd9\u79cd\u51fd\u6570\u7684\u7528\u6237\u4e5f\u53ef\u80fd\u5e0c\u671b\u5728\u51fd\u6570\u8c03\u7528\u4e2d\u4f7f\u7528 <code class=\"literal\">VARIADIC</code> \u5173\u952e\u5b57\uff0c\u4ee5\u4fbf\u8ba9\u51fd\u6570\u628a\u6570\u7ec4\u5143\u7d20\u5f53\u4f5c\u72ec\u7acb\u53c2\u6570\u5904\u7406\u3002\u5982\u679c\u5e0c\u671b\u652f\u6301\u8fd9\u79cd\u884c\u4e3a\uff0c\u51fd\u6570\u672c\u8eab\u5c31\u5fc5\u987b\u5728\u4f7f\u7528 <code class=\"function\">get_fn_expr_variadic</code> \u68c0\u6d4b\u5230\u5b9e\u53c2\u88ab\u6807\u8bb0\u4e3a <code class=\"literal\">VARIADIC</code> \u540e\u81ea\u884c\u5b9e\u73b0\u5b83\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-SHARED-ADDIN\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-SHARED-ADDIN\">36.10.11. \u5171\u4eab\u5185\u5b58</a></span></h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u3002\u4e3a\u6b64\uff0c\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\uff0c\u5e76\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\u3002\u6b64\u94a9\u5b50\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559\u5171\u4eab\u5185\u5b58\uff1a</p>\n<pre class=\"programlisting\">void RequestAddinShmemSpace(Size size)\n</pre>\n<p lang=\"zh\">\u6765\u9884\u7559\u5171\u4eab\u5185\u5b58\u3002\u6bcf\u4e2a\u540e\u7aef\u90fd\u5e94\u5f53\u901a\u8fc7\u8c03\u7528\uff1a</p>\n<pre class=\"programlisting\">void *ShmemInitStruct(const char *name, Size size, bool *foundPtr)\n</pre>\n<p lang=\"zh\">\u6765\u83b7\u53d6\u6307\u5411\u8fd9\u5757\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u6307\u9488\u3002\u5982\u679c\u8be5\u51fd\u6570\u628a <code class=\"literal\">foundPtr</code> \u8bbe\u4e3a <code class=\"literal\">false</code>\uff0c\u8c03\u7528\u8005\u5c31\u5e94\u521d\u59cb\u5316\u8fd9\u5757\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u5185\u5bb9\uff1b\u5982\u679c <code class=\"literal\">foundPtr</code> \u4e3a <code class=\"literal\">true</code>\uff0c\u8bf4\u660e\u8be5\u5171\u4eab\u5185\u5b58\u5df2\u7ecf\u7531\u5176\u4ed6\u540e\u7aef\u521d\u59cb\u5316\u8fc7\uff0c\u8c03\u7528\u8005\u65e0\u9700\u518d\u505a\u521d\u59cb\u5316\u3002</p>\n<p lang=\"zh\">\u4e3a\u907f\u514d\u7ade\u4e89\u6761\u4ef6\uff0c\u6bcf\u4e2a\u540e\u7aef\u5728\u521d\u59cb\u5316\u5176\u5171\u4eab\u5185\u5b58\u5206\u914d\u65f6\u90fd\u5e94\u4f7f\u7528 LWLock <code class=\"function\">AddinShmemInitLock</code>\uff0c\u5982\u4e0b\u6240\u793a\uff1a</p>\n<pre class=\"programlisting\">static mystruct *ptr = NULL;\nbool        found;\n\nLWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);\nptr = ShmemInitStruct(\"my struct name\", size, &amp;found);\nif (!found)\n{\n    ... initialize contents of shared memory ...\n    ptr-&gt;locks = GetNamedLWLockTranche(\"my tranche name\");\n}\nLWLockRelease(AddinShmemInitLock);\n</pre>\n<p lang=\"zh\"><code class=\"literal\">shmem_startup_hook</code> \u4e3a\u521d\u59cb\u5316\u4ee3\u7801\u63d0\u4f9b\u4e86\u4e00\u4e2a\u65b9\u4fbf\u7684\u4f4d\u7f6e\uff0c\u4f46\u5e76\u4e0d\u5f3a\u5236\u8981\u6c42\u6240\u6709\u8fd9\u7c7b\u4ee3\u7801\u90fd\u653e\u5728\u8fd9\u4e2a\u94a9\u5b50\u4e2d\u3002\u5728 Windows \u4e0a\uff08\u4ee5\u53ca\u4efb\u4f55\u5b9a\u4e49\u4e86 <code class=\"literal\">EXEC_BACKEND</code> \u7684\u5e73\u53f0\u4e0a\uff09\uff0c\u6bcf\u4e2a\u540e\u7aef\u90fd\u4f1a\u5728\u9644\u52a0\u5230\u5171\u4eab\u5185\u5b58\u540e\u4e0d\u4e45\u6267\u884c\u5df2\u6ce8\u518c\u7684 <code class=\"literal\">shmem_startup_hook</code>\uff0c\u56e0\u6b64\u63d2\u4ef6\u5728\u8be5\u94a9\u5b50\u4e2d\u4ecd\u5e94\u50cf\u4e0a\u4f8b\u90a3\u6837\u83b7\u53d6 <code class=\"function\">AddinShmemInitLock</code>\u3002\u5728\u5176\u4ed6\u5e73\u53f0\u4e0a\uff0c\u53ea\u6709 postmaster \u8fdb\u7a0b\u4f1a\u6267\u884c <code class=\"literal\">shmem_startup_hook</code>\uff0c\u6bcf\u4e2a\u540e\u7aef\u4f1a\u81ea\u52a8\u7ee7\u627f\u8fd9\u4e9b\u5171\u4eab\u5185\u5b58\u6307\u9488\u3002</p>\n<p lang=\"zh\"><code class=\"literal\">shmem_request_hook</code> \u4e0e <code class=\"literal\">shmem_startup_hook</code> \u7684\u4e00\u4e2a\u5b8c\u6574\u793a\u4f8b\u53ef\u89c1\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_stat_statements/pg_stat_statements.c</code>\u3002</p>\n</div>\n<div class=\"sect3\" id=\"XFUNC-SHARED-ADDIN-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.11.2.\u00a0\u542f\u52a8\u540e\u8bf7\u6c42\u5171\u4eab\u5185\u5b58 </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u9884\u7559\u5171\u4eab\u5185\u5b58\u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u4e4b\u540e\uff0c\u5e76\u4e14\u65e0\u9700\u501f\u52a9 <code class=\"literal\">shmem_request_hook</code> \u6765\u5b8c\u6210\u3002\u4e3a\u6b64\uff0c\u6bcf\u4e2a\u9700\u8981\u4f7f\u7528\u8be5\u5171\u4eab\u5185\u5b58\u7684\u540e\u7aef\u90fd\u5e94\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u83b7\u53d6\u4e00\u4e2a\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">void *GetNamedDSMSegment(const char *name, size_t size,\n                         void (*init_callback) (void *ptr),\n                         bool *found)\n</pre>\n<p lang=\"zh\">\u5982\u679c\u7ed9\u5b9a\u540d\u79f0\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u5c1a\u4e0d\u5b58\u5728\uff0c\u8be5\u51fd\u6570\u4f1a\u5206\u914d\u8be5\u6bb5\uff0c\u5e76\u4f7f\u7528\u63d0\u4f9b\u7684 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u5bf9\u5176\u8fdb\u884c\u521d\u59cb\u5316\u3002\u5982\u679c\u8be5\u6bb5\u5df2\u7ecf\u7531\u53e6\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8fc7\uff0c\u8be5\u51fd\u6570\u5c31\u53ea\u4f1a\u628a\u73b0\u6709\u7684\u52a8\u6001\u5171\u4eab\u5185\u5b58\u6bb5\u9644\u52a0\u5230\u5f53\u524d\u540e\u7aef\u3002</p>\n<p lang=\"zh\">\u4e0e\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559\u7684\u5171\u4eab\u5185\u5b58\u4e0d\u540c\uff0c\u4f7f\u7528 GetNamedDSMSegment \u9884\u7559\u5171\u4eab\u5185\u5b58\u65f6\uff0c\u65e0\u9700\u83b7\u53d6 AddinShmemInitLock\uff0c\u4e5f\u65e0\u9700\u91c7\u53d6\u5176\u4ed6\u63aa\u65bd\u907f\u514d\u7ade\u6001\u6761\u4ef6\u3002\u6b64\u51fd\u6570\u4fdd\u8bc1\u4ec5\u7531\u4e00\u4e2a\u540e\u7aef\u5206\u914d\u5e76\u521d\u59cb\u5316\u8be5\u6bb5\uff0c\u5176\u4ed6\u6240\u6709\u540e\u7aef\u83b7\u5f97\u7684\u90fd\u662f\u6307\u5411\u5df2\u5b8c\u5168\u5206\u914d\u5e76\u521d\u59cb\u5316\u7684\u6bb5\u7684\u6307\u9488\u3002</p>\n<p lang=\"zh\"><code class=\"function\">GetNamedDSMSegment</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/test_dsm_registry/test_dsm_registry.c</code>\uff0c\u4f4d\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-LWLOCKS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\">36.10.12. \u8f7b\u91cf\u7ea7\u9501\uff08LWLocks\uff09</h3>\n</div>\n</div>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AT-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.12.1.\u00a0\u542f\u52a8\u65f6\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u9644\u52a0\u6a21\u5757\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u65f6\u9884\u7559 LWLocks\u3002\u4e0e\u542f\u52a8\u65f6\u9884\u7559\u5171\u4eab\u5185\u5b58\u4e00\u6837\uff0c\u5fc5\u987b\u901a\u8fc7 shared_preload_libraries \u9884\u52a0\u8f7d\u6a21\u5757\u7684\u5171\u4eab\u5e93\uff0c\u5e76\u5728\u5176 _PG_init \u51fd\u6570\u4e2d\u6ce8\u518c shmem_request_hook\u3002\u6b64\u94a9\u5b50\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u9884\u7559 LWLocks\uff1a</p>\n<pre class=\"programlisting\">void RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)\n</pre>\n<p lang=\"zh\">\u8fd9\u786e\u4fdd\u5b58\u5728\u4e00\u4e2a\u540d\u4e3a tranche_name\u3001\u5305\u542b num_lwlocks \u4e2a LWLocks \u7684\u6570\u7ec4\u3002\u53ef\u901a\u8fc7\u4ee5\u4e0b\u8c03\u7528\u53d6\u5f97\u8be5\u6570\u7ec4\u7684\u6307\u9488\uff1a</p>\n<pre class=\"programlisting\">LWLockPadded *GetNamedLWLockTranche(const char *tranche_name)\n</pre>\n</div>\n<div class=\"sect3\" id=\"XFUNC-ADDIN-LWLOCKS-AFTER-STARTUP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h4 class=\"title\" lang=\"zh\">\n<div>\n<div>\n<h4 class=\"title\">36.10.12.2.\u00a0\u542f\u52a8\u540e\u8bf7\u6c42 LWLocks </h4>\n</div>\n</div>\n</h4>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u8fd8\u6709\u53e6\u4e00\u79cd\u66f4\u7075\u6d3b\u7684\u83b7\u53d6 LWLocks \u7684\u65b9\u6cd5\uff0c\u53ef\u4ee5\u5728\u670d\u52a1\u5668\u542f\u52a8\u540e\u8fdb\u884c\uff0c\u4e5f\u65e0\u9700\u501f\u52a9 <code class=\"literal\">shmem_request_hook</code>\u3002\u4e3a\u6b64\uff0c\u9996\u5148\u901a\u8fc7\u8c03\u7528\u4e0b\u9762\u7684\u51fd\u6570\u5206\u914d\u4e00\u4e2a <code class=\"literal\">tranche_id</code>\uff1a</p>\n<pre class=\"programlisting\">int LWLockNewTrancheId(void)\n</pre>\n<p lang=\"zh\">\u63a5\u4e0b\u6765\uff0c\u521d\u59cb\u5316\u6bcf\u4e2a LWLock\uff0c\u5e76\u628a\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\uff1a</p>\n<pre class=\"programlisting\">void LWLockInitialize(LWLock *lock, int tranche_id)\n</pre>\n<p lang=\"zh\">\u4e0e\u5171\u4eab\u5185\u5b58\u7c7b\u4f3c\uff0c\u6bcf\u4e2a\u540e\u7aef\u90fd\u5e94\u786e\u4fdd\u53ea\u6709\u4e00\u4e2a\u8fdb\u7a0b\u4f1a\u5206\u914d\u65b0\u7684 <code class=\"literal\">tranche_id</code> \u5e76\u521d\u59cb\u5316\u6bcf\u4e00\u4e2a\u65b0\u7684 LWLock\u3002\u4e00\u79cd\u505a\u6cd5\u662f\u4ec5\u5728\u6301\u6709 <code class=\"function\">AddinShmemInitLock</code> \u72ec\u5360\u9501\u7684\u5171\u4eab\u5185\u5b58\u521d\u59cb\u5316\u4ee3\u7801\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u3002\u5982\u679c\u4f7f\u7528 <code class=\"function\">GetNamedDSMSegment</code>\uff0c\u90a3\u4e48\u5728 <code class=\"function\">init_callback</code> \u56de\u8c03\u51fd\u6570\u4e2d\u8c03\u7528\u8fd9\u4e9b\u51fd\u6570\u5c31\u8db3\u4ee5\u907f\u514d\u7ade\u4e89\u6761\u4ef6\u3002</p>\n<p lang=\"zh\">\u6700\u540e\uff0c\u6bcf\u4e2a\u4f7f\u7528\u8be5 <code class=\"literal\">tranche_id</code> \u7684\u540e\u7aef\u90fd\u5e94\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u628a\u5b83\u4e0e\u4e00\u4e2a <code class=\"literal\">tranche_name</code> \u5173\u8054\u8d77\u6765\uff1a</p>\n<pre class=\"programlisting\">void LWLockRegisterTranche(int tranche_id, const char *tranche_name)\n</pre>\n<p lang=\"zh\"><code class=\"function\">LWLockNewTrancheId</code>\u3001<code class=\"function\">LWLockInitialize</code> \u548c <code class=\"function\">LWLockRegisterTranche</code> \u7684\u5b8c\u6574\u4f7f\u7528\u793a\u4f8b\u53ef\u89c1\u4e8e <span class=\"productname\">PostgreSQL</span> \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">contrib/pg_prewarm/autoprewarm.c</code>\u3002</p>\n</div>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-WAIT-EVENTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-ADDIN-WAIT-EVENTS\">36.10.13. \u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u5728\u7b49\u5f85\u4e8b\u4ef6\u7c7b\u578b <code class=\"literal\">Extension</code> \u4e0b\u5b9a\u4e49\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\uff1a</p>\n<pre class=\"programlisting\">uint32 WaitEventExtensionNew(const char *wait_event_name)\n</pre>\n<p lang=\"zh\">\u8be5\u7b49\u5f85\u4e8b\u4ef6\u4f1a\u5173\u8054\u5230\u4e00\u4e2a\u9762\u5411\u7528\u6237\u7684\u81ea\u5b9a\u4e49\u5b57\u7b26\u4e32\u3002\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/worker_spi</code>\uff0c\u4f4d\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u3002</p>\n<p lang=\"zh\">\u81ea\u5b9a\u4e49\u7b49\u5f85\u4e8b\u4ef6\u53ef\u4ee5\u5728 <a class=\"link\" href=\"/docs/18/monitoring-stats.html#MONITORING-PG-STAT-ACTIVITY-VIEW\" title=\"27.2.3.\u00a0pg_stat_activity\"><code class=\"structname\">pg_stat_activity</code></a> \u4e2d\u67e5\u770b\uff1a</p>\n<pre class=\"screen\">=# SELECT wait_event_type, wait_event FROM pg_stat_activity\n     WHERE backend_type ~ 'worker_spi';\n wait_event_type |  wait_event\n-----------------+---------------\n Extension       | WorkerSpiMain\n(1 row)\n</pre>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-INJECTION-POINTS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-ADDIN-INJECTION-POINTS\">36.10.14. \u6ce8\u5165\u70b9</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7ed9\u5b9a\u540d\u79f0 <code class=\"literal\">name</code> \u7684\u6ce8\u5165\u70b9\u53ef\u901a\u8fc7\u4ee5\u4e0b\u5b8f\u58f0\u660e\uff1a</p>\n<pre class=\"programlisting\">INJECTION_POINT(name, arg);\n</pre>\n<p lang=\"zh\">\u670d\u52a1\u5668\u4ee3\u7801\u4e2d\u5df2\u7ecf\u5728\u82e5\u5e72\u5173\u952e\u4f4d\u7f6e\u58f0\u660e\u4e86\u6ce8\u5165\u70b9\u3002\u65b0\u589e\u6ce8\u5165\u70b9\u540e\uff0c\u9700\u8981\u91cd\u65b0\u7f16\u8bd1\u4ee3\u7801\uff0c\u624d\u80fd\u8ba9\u8be5\u6ce8\u5165\u70b9\u51fa\u73b0\u5728\u4e8c\u8fdb\u5236\u6587\u4ef6\u4e2d\u3002\u7528 C \u8bed\u8a00\u7f16\u5199\u7684\u63d2\u4ef6\u4e5f\u53ef\u4ee5\u4f7f\u7528\u540c\u4e00\u4e2a\u5b8f\u5728\u81ea\u5df1\u7684\u4ee3\u7801\u4e2d\u58f0\u660e\u6ce8\u5165\u70b9\u3002\u6ce8\u5165\u70b9\u540d\u79f0\u5e94\u4f7f\u7528\u5c0f\u5199\u5b57\u6bcd\uff0c\u5e76\u7528\u8fde\u5b57\u7b26\u5206\u9694\u5404\u4e2a\u672f\u8bed\u3002<code class=\"literal\">arg</code> \u662f\u8fd0\u884c\u65f6\u4f20\u7ed9\u56de\u8c03\u7684\u53ef\u9009\u53c2\u6570\u503c\u3002</p>\n<p lang=\"zh\">\u6267\u884c\u6ce8\u5165\u70b9\u53ef\u80fd\u9700\u8981\u5206\u914d\u5c11\u91cf\u5185\u5b58\uff0c\u800c\u8fd9\u53ef\u80fd\u5931\u8d25\u3002\u5982\u679c\u4f60\u9700\u8981\u5728\u4e00\u4e2a\u4e0d\u5141\u8bb8\u52a8\u6001\u5206\u914d\u7684\u4e34\u754c\u533a\u4e2d\u4f7f\u7528\u6ce8\u5165\u70b9\uff0c\u53ef\u4ee5\u91c7\u7528\u4ee5\u4e0b\u4e24\u6b65\u6cd5\uff1a</p>\n<pre class=\"programlisting\">INJECTION_POINT_LOAD(name);\nINJECTION_POINT_CACHED(name, arg);\n</pre>\n<p lang=\"zh\">\u5728\u8fdb\u5165\u4e34\u754c\u533a\u4e4b\u524d\uff0c\u8c03\u7528 <code class=\"function\">INJECTION_POINT_LOAD</code>\u3002\u5b83\u4f1a\u68c0\u67e5\u5171\u4eab\u5185\u5b58\u72b6\u6001\uff0c\u5e76\u5728\u8be5\u6ce8\u5165\u70b9\u5904\u4e8e\u6fc0\u6d3b\u72b6\u6001\u65f6\u628a\u56de\u8c03\u52a0\u8f7d\u5230\u540e\u7aef\u79c1\u6709\u5185\u5b58\u4e2d\u3002\u5728\u4e34\u754c\u533a\u5185\u90e8\uff0c\u518d\u7528 <code class=\"function\">INJECTION_POINT_CACHED</code> \u6765\u6267\u884c\u56de\u8c03\u3002</p>\n<p lang=\"zh\">\u63d2\u4ef6\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\uff0c\u4e3a\u4e00\u4e2a\u5df2\u7ecf\u58f0\u660e\u597d\u7684\u6ce8\u5165\u70b9\u9644\u52a0\u56de\u8c03\uff1a</p>\n<pre class=\"programlisting\">extern void InjectionPointAttach(const char *name,\n                                 const char *library,\n                                 const char *function,\n                                 const void *private_data,\n                                 int private_data_size);\n</pre>\n<p lang=\"zh\">name \u662f\u6ce8\u5165\u70b9\u7684\u540d\u79f0\uff1b\u6267\u884c\u5230\u8fbe\u6b64\u6ce8\u5165\u70b9\u65f6\uff0c\u5c06\u6267\u884c\u4ece library \u52a0\u8f7d\u7684\u51fd\u6570\u3002private_data \u662f\u4e00\u5757\u5927\u5c0f\u4e3a private_data_size \u7684\u79c1\u6709\u6570\u636e\u533a\u57df\uff0c\u5728\u6267\u884c\u56de\u8c03\u65f6\u4f5c\u4e3a\u53c2\u6570\u4f20\u5165\u3002</p>\n<p lang=\"zh\">\u4e0b\u9762\u662f\u4e00\u4e2a <code class=\"literal\">InjectionPointCallback</code> \u7684\u793a\u4f8b\uff1a</p>\n<pre class=\"programlisting\">static void\ncustom_injection_callback(const char *name,\n                          const void *private_data,\n                          void *arg)\n{\n    uint32 wait_event_info = WaitEventInjectionPointNew(name);\n\n    pgstat_report_wait_start(wait_event_info);\n    elog(NOTICE, \"%s: executed custom callback\", name);\n    pgstat_report_wait_end();\n}\n</pre>\n<p lang=\"zh\">\u8fd9\u4e2a\u56de\u8c03\u4f1a\u4ee5 <code class=\"literal\">NOTICE</code> \u7ea7\u522b\u5411\u670d\u52a1\u5668\u9519\u8bef\u65e5\u5fd7\u5199\u5165\u4e00\u6761\u6d88\u606f\uff0c\u4f46\u56de\u8c03\u5b8c\u5168\u53ef\u4ee5\u5b9e\u73b0\u66f4\u590d\u6742\u7684\u903b\u8f91\u3002</p>\n<p lang=\"zh\">\u53e6\u4e00\u79cd\u5b9a\u4e49\u201c\u5230\u8fbe\u6ce8\u5165\u70b9\u65f6\u5e94\u6267\u884c\u4ec0\u4e48\u52a8\u4f5c\u201d\u7684\u65b9\u5f0f\uff0c\u662f\u628a\u6d4b\u8bd5\u4ee3\u7801\u76f4\u63a5\u5199\u5728\u5e38\u89c4\u6e90\u4ee3\u7801\u65c1\u8fb9\u3002\u5982\u679c\u8be5\u52a8\u4f5c\u4f9d\u8d56\u4e8e\u52a0\u8f7d\u6a21\u5757\u65e0\u6cd5\u8bbf\u95ee\u7684\u5c40\u90e8\u53d8\u91cf\uff0c\u8fd9\u4f1a\u5f88\u6709\u7528\u3002\u6b64\u65f6\u53ef\u4ee5\u4f7f\u7528 <code class=\"function\">IS_INJECTION_POINT_ATTACHED</code> \u5b8f\u6765\u68c0\u67e5\u67d0\u4e2a\u6ce8\u5165\u70b9\u662f\u5426\u5df2\u9644\u52a0\uff0c\u4f8b\u5982\uff1a</p>\n<pre class=\"programlisting\">#ifdef USE_INJECTION_POINTS\nif (IS_INJECTION_POINT_ATTACHED(\"before-foobar\"))\n{\n    /* change a local variable if injection point is attached */\n    local_var = 123;\n\n    /* also execute the callback */\n    INJECTION_POINT_CACHED(\"before-foobar\", NULL);\n}\n#endif\n</pre>\n<p lang=\"zh\">\u6ce8\u610f\uff0c\u9644\u52a0\u5230\u6ce8\u5165\u70b9\u4e0a\u7684\u56de\u8c03\u4e0d\u4f1a\u7531 <code class=\"function\">IS_INJECTION_POINT_ATTACHED</code> \u5b8f\u6267\u884c\u3002\u5982\u679c\u4f60\u60f3\u6267\u884c\u8be5\u56de\u8c03\uff0c\u5c31\u5fc5\u987b\u50cf\u4e0a\u9762\u7684\u793a\u4f8b\u90a3\u6837\u53e6\u5916\u8c03\u7528 <code class=\"function\">INJECTION_POINT_CACHED</code>\u3002</p>\n<p lang=\"zh\">\u53ef\u9009\u5730\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u8c03\u7528\u4ee5\u4e0b\u51fd\u6570\u6765\u89e3\u9664\u4e00\u4e2a\u6ce8\u5165\u70b9\uff1a</p>\n<pre class=\"programlisting\">extern bool InjectionPointDetach(const char *name);\n</pre>\n<p lang=\"zh\">\u6210\u529f\u65f6\u8fd4\u56de <code class=\"literal\">true</code>\uff0c\u5426\u5219\u8fd4\u56de <code class=\"literal\">false</code>\u3002</p>\n<p lang=\"zh\">\u4e00\u4e2a\u9644\u52a0\u5230\u6ce8\u5165\u70b9\u7684\u56de\u8c03\u4f1a\u5728\u6240\u6709\u540e\u7aef\u4e2d\u751f\u6548\uff0c\u5305\u62ec\u5728\u8c03\u7528 <code class=\"literal\">InjectionPointAttach</code> \u4e4b\u540e\u624d\u542f\u52a8\u7684\u540e\u7aef\u3002\u5b83\u4f1a\u4e00\u76f4\u4fdd\u6301\u9644\u52a0\u72b6\u6001\uff0c\u76f4\u5230\u670d\u52a1\u5668\u505c\u6b62\uff0c\u6216\u8005\u901a\u8fc7 <code class=\"literal\">InjectionPointDetach</code> \u5c06\u5176\u89e3\u9664\u3002</p>\n<p lang=\"zh\">\u76f8\u5173\u793a\u4f8b\u53ef\u89c1\u4e8e PostgreSQL \u6e90\u4ee3\u7801\u6811\u4e2d\u7684 <code class=\"filename\">src/test/modules/injection_points</code>\u3002</p>\n<p lang=\"zh\">\u8981\u542f\u7528\u6ce8\u5165\u70b9\uff0c\u4f7f\u7528 configure \u65f6\u9700\u6307\u5b9a --enable-injection-points\uff0c\u4f7f\u7528 Meson \u65f6\u9700\u6307\u5b9a -Dinjection_points=true\u3002</p>\n</div>\n<div class=\"sect2\" id=\"XFUNC-ADDIN-CUSTOM-CUMULATIVE-STATISTICS\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#XFUNC-ADDIN-CUSTOM-CUMULATIVE-STATISTICS\">36.10.15. \u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u7528 C \u8bed\u8a00\u7f16\u5199\u7684\u63d2\u4ef6\u53ef\u4ee5\u4f7f\u7528\u5728<a class=\"link\" href=\"/docs/18/monitoring-stats.html#MONITORING-STATS-SETUP\" title=\"27.2.1.\u00a0\u7edf\u8ba1\u4fe1\u606f\u6536\u96c6\u914d\u7f6e\">\u7d2f\u8ba1\u7edf\u8ba1\u7cfb\u7edf</a>\u4e2d\u6ce8\u518c\u7684\u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1\u7c7b\u578b\u3002</p>\n<p lang=\"zh\">\u9996\u5148\uff0c\u5b9a\u4e49\u4e00\u4e2a <code class=\"literal\">PgStat_KindInfo</code>\uff0c\u5176\u4e2d\u5305\u542b\u4e0e\u6240\u6ce8\u518c\u81ea\u5b9a\u4e49\u7c7b\u578b\u76f8\u5173\u7684\u5168\u90e8\u4fe1\u606f\u3002\u4f8b\u5982\uff1a</p>\n<pre class=\"programlisting\">static const PgStat_KindInfo custom_stats = {\n    .name = \"custom_stats\",\n    .fixed_amount = false,\n    .shared_size = sizeof(PgStatShared_Custom),\n    .shared_data_off = offsetof(PgStatShared_Custom, stats),\n    .shared_data_len = sizeof(((PgStatShared_Custom *) 0)-&gt;stats),\n    .pending_size = sizeof(PgStat_StatCustomEntry),\n}\n</pre>\n<p lang=\"zh\">\u7136\u540e\uff0c\u6bcf\u4e2a\u9700\u8981\u4f7f\u7528\u8fd9\u79cd\u81ea\u5b9a\u4e49\u7c7b\u578b\u7684\u540e\u7aef\uff0c\u90fd\u9700\u8981\u4f7f\u7528 <code class=\"literal\">pgstat_register_kind</code> \u6ce8\u518c\u5b83\uff0c\u5e76\u6307\u5b9a\u4e00\u4e2a\u7528\u4e8e\u5b58\u50a8\u8be5\u7c7b\u7edf\u8ba1\u6761\u76ee\u7684\u552f\u4e00 ID\uff1a</p>\n<pre class=\"programlisting\">extern PgStat_Kind pgstat_register_kind(PgStat_Kind kind,\n                                        const PgStat_KindInfo *kind_info);\n</pre>\n<p lang=\"zh\">\u5728\u5f00\u53d1\u65b0\u6269\u5c55\u65f6\uff0c\u5e94\u5c06 <code class=\"literal\">PGSTAT_KIND_EXPERIMENTAL</code> \u7528\u4f5c <em class=\"parameter\"><code>kind</code></em>\u3002\u5f53\u4f60\u51c6\u5907\u628a\u6269\u5c55\u53d1\u5e03\u7ed9\u7528\u6237\u65f6\uff0c\u8bf7\u5728 <a class=\"ulink\" href=\"https://wiki.postgresql.org/wiki/CustomCumulativeStats\" target=\"_top\">Custom Cumulative Statistics</a> \u9875\u9762\u4e0a\u9884\u7559\u4e00\u4e2a kind ID\u3002</p>\n<p lang=\"zh\">\u5173\u4e8e <code class=\"literal\">PgStat_KindInfo</code> API \u7684\u7ec6\u8282\uff0c\u53ef\u89c1 <code class=\"filename\">src/include/utils/pgstat_internal.h</code>\u3002</p>\n<p lang=\"zh\">\u5df2\u6ce8\u518c\u7684\u7edf\u8ba1\u7c7b\u578b\u4f1a\u5173\u8054\u5230\u4e00\u4e2a\u540d\u79f0\u4ee5\u53ca\u4e00\u4e2a\u5728\u5171\u4eab\u5185\u5b58\u4e2d\u4f9b\u6574\u4e2a\u670d\u52a1\u5668\u5171\u4eab\u7684\u552f\u4e00 ID\u3002\u6bcf\u4e2a\u4f7f\u7528\u81ea\u5b9a\u4e49\u7edf\u8ba1\u7c7b\u578b\u7684\u540e\u7aef\u90fd\u4f1a\u7ef4\u62a4\u4e00\u4e2a\u672c\u5730\u7f13\u5b58\uff0c\u7528\u6765\u4fdd\u5b58\u5404\u4e2a\u81ea\u5b9a\u4e49 <code class=\"literal\">PgStat_KindInfo</code> \u7684\u4fe1\u606f\u3002</p>\n<p lang=\"zh\">\u5e94\u5c06\u5b9e\u73b0\u81ea\u5b9a\u4e49\u7d2f\u8ba1\u7edf\u8ba1\u7c7b\u578b\u7684\u6269\u5c55\u6a21\u5757\u52a0\u5165<a class=\"xref\" href=\"/docs/18/runtime-config-client.html#GUC-SHARED-PRELOAD-LIBRARIES\">shared_preload_libraries</a>\uff0c\u4ee5\u4fbf\u5728 <span class=\"productname\">PostgreSQL</span> \u542f\u52a8\u671f\u95f4\u5c3d\u65e9\u8f7d\u5165\u3002</p>\n<p lang=\"zh\">\u5c55\u793a\u5982\u4f55\u6ce8\u518c\u5e76\u4f7f\u7528\u81ea\u5b9a\u4e49\u7edf\u8ba1\u4fe1\u606f\u7684\u793a\u4f8b\u53ef\u89c1\u4e8e <code class=\"filename\">src/test/modules/injection_points</code>\u3002</p>\n</div>\n<div class=\"sect2\" id=\"EXTEND-CPP\">\n<div class=\"titlepage\">\n<div>\n<div>\n<h3 class=\"title\" lang=\"zh\"><span class=\"sect2\"><a href=\"/docs/18/xfunc-c.html#EXTEND-CPP\">36.10.16. \u628a C++ \u7528\u4e8e\u53ef\u6269\u5c55\u6027</a></span></h3>\n</div>\n</div>\n</div>\n<p lang=\"zh\">\u5c3d\u7ba1<span class=\"productname\">PostgreSQL</span>\u540e\u7aef\u662f\u7528 C \u7f16\u5199\u7684\uff0c\u53ea\u8981\u9075\u5faa\u4e0b\u9762\u7684\u6307\u5bfc\u65b9\u9488\u4e5f\u53ef\u4ee5\u7528 C++ \u7f16\u5199\u6269\u5c55\uff1a</p>\n<div class=\"itemizedlist\">\n<ul class=\"itemizedlist\">\n<li class=\"listitem\" lang=\"zh\">\n<p>\u6240\u6709\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u5fc5\u987b\u5bf9\u540e\u7aef\u5448\u73b0\u4e00\u79cd C \u63a5\u53e3\uff0c\u7136\u540e\u8fd9\u4e9b C \u51fd\u6570\u8c03\u7528 C++ \u51fd\u6570\u3002\u4f8b\u5982\uff0c\u88ab\u540e\u7aef\u8bbf\u95ee\u7684\u51fd\u6570\u8981\u6c42<code class=\"literal\">extern C</code> \u94fe\u63a5\u3002\u5bf9\u9700\u8981\u5728\u540e\u7aef\u548c C++ \u4ee3\u7801\u4e4b\u95f4\u4f5c\u4e3a\u6307\u9488\u4f20\u9012\u7684\u4efb\u4f55\u51fd\u6570\u4e5f\u8981\u8fd9\u6837\u505a\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u4f7f\u7528\u5408\u9002\u7684\u91ca\u653e\u65b9\u6cd5\u91ca\u653e\u5185\u5b58\u3002\u4f8b\u5982\uff0c\u5927\u90e8\u5206\u540e\u7aef\u5185\u5b58\u662f\u901a\u8fc7 <code class=\"function\">palloc()</code>\u5206\u914d\u7684\uff0c\u6240\u4ee5\u5e94\u4f7f\u7528<code class=\"function\">pfree()</code> \u6765\u91ca\u653e\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e2d\u4f7f\u7528 C++ \u7684<code class=\"function\">delete</code>\u4f1a\u5931\u8d25\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\n<p>\u9632\u6b62\u5f02\u5e38\u4f20\u64ad\u5230 C \u4ee3\u7801\u4e2d\uff08\u5728\u6240\u6709<code class=\"literal\">extern C</code>\u51fd\u6570\u7684\u9876\u5c42\u4f7f\u7528\u4e00\u4e2a\u6355\u6349\u5168\u90e8\u5f02\u5e38\u7684\u5757\uff09\u3002\u5373\u4f7f C++ \u4ee3\u7801\u4e0d\u4f1a\u663e\u5f0f\u5730\u629b\u51fa\u4efb\u4f55\u5f02\u5e38\u4e5f\u9700\u8981\u8fd9\u6837\u505a\uff0c\u56e0\u4e3a\u7c7b\u4f3c\u5185\u5b58\u4e0d\u8db3\u7b49\u4e8b\u4ef6\u4ecd\u4f1a\u629b\u51fa\u5f02\u5e38\u3002\u4efb\u4f55\u5f02\u5e38\u90fd\u5fc5\u987b\u88ab\u6355\u6349\u5e76\u4e14\u7528\u9002\u5f53\u7684\u9519\u8bef\u4f20\u56de\u7ed9 C \u63a5\u53e3\u3002\u5982\u679c\u53ef\u80fd\uff0c\u7528 <code class=\"option\">-fno-exceptions</code> \u6765\u7f16\u8bd1 C++ \u4ee5\u5b8c\u5168\u6d88\u706d\u5f02\u5e38\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u4f60\u5fc5\u987b\u5728 C++ \u4ee3\u7801\u4e2d\u68c0\u67e5\u5931\u8d25\uff0c\u4f8b\u5982\u68c0\u67e5<code class=\"function\">new()</code> \u8fd4\u56de\u7684 NULL\u3002</p>\n</li>\n<li class=\"listitem\" lang=\"zh\">\u4ece C++ \u4ee3\u7801\u8c03\u7528\u540e\u7aef\u51fd\u6570\u65f6\uff0c\u5fc5\u987b\u786e\u4fdd C++ \u8c03\u7528\u6808\u4e2d\u4ec5\u5305\u542b\u666e\u901a\u65e7\u5f0f\u6570\u636e\u7ed3\u6784\uff08POD\uff09\u3002\u8fd9\u662f\u56e0\u4e3a\u540e\u7aef\u9519\u8bef\u4f1a\u89e6\u53d1\u8fdc\u8ddd\u79bb longjmp()\uff0c\u65e0\u6cd5\u6b63\u786e\u5c55\u5f00\u5305\u542b\u975e POD \u5bf9\u8c61\u7684 C++ \u8c03\u7528\u6808\u3002</li>\n</ul>\n</div>\n<p lang=\"zh\">\u603b\u4e4b\uff0c\u6700\u597d\u628a C++ \u4ee3\u7801\u653e\u5728\u4e0e\u540e\u7aef\u4ea4\u4e92\u7684<code class=\"literal\">extern C</code>\u51fd\u6570\u4e4b\u540e\uff0c\u5e76\u4e14\u907f\u514d\u5f02\u5e38\u3001\u5185\u5b58\u548c\u8c03\u7528\u6808\u6cc4\u6f0f\u3002</p>\n</div>\n</div>", "manual_path": "/docs/18/xfunc-c.html", "localization": {"status": "complete", "sources": [{"url": "/docs/18/protocol-overview.html", "method": "same-major semantic node", "sha256": "3f1aa8bd4dbef58e9a82e8cf4c82829a4df7416cfa83dd61c18e9e25060f22da", "language": "zh", "matched_nodes": ["#PROTOCOL-OVERVIEW/div[9]/p[1]/span[2]/span[0]"]}, {"url": "/docs/18/xfunc-c.html", "method": "same-major semantic node", "sha256": "4b35ab16ac85cc22b5c37555941784a2fd0a1b66b507e9dfff9a239102c15e77", "language": "zh", "matched_nodes": ["#XFUNC-C/div[0]", "#XFUNC-C/div[10]/div[2]/div[0]", "#XFUNC-C/div[10]/div[2]/p[2]", "#XFUNC-C/div[10]/div[3]/div[0]", "#XFUNC-C/div[10]/div[3]/div[2]/p[1]", "#XFUNC-C/div[10]/div[3]/div[3]/p[1]", "#XFUNC-C/div[10]/div[3]/div[3]/p[2]", "#XFUNC-C/div[10]/div[4]/div[0]", "#XFUNC-C/div[10]/div[4]/div[2]/p[1]", "#XFUNC-C/div[10]/div[4]/div[3]/p[1]", "#XFUNC-C/div[10]/div[4]/div[3]/p[2]", "#XFUNC-C/div[10]/div[4]/div[3]/p[3]", "#XFUNC-C/div[10]/div[4]/div[3]/p[4]", "#XFUNC-C/div[10]/div[4]/div[3]/p[5]", "#XFUNC-C/div[10]/p[1]", "#XFUNC-C/div[11]/p[10]", "#XFUNC-C/div[11]/p[1]", "#XFUNC-C/div[11]/p[2]", "#XFUNC-C/div[11]/p[6]", "#XFUNC-C/div[11]/p[7]", "#XFUNC-C/div[11]/p[8]", "#XFUNC-C/div[12]/div[7]/p[1]", "#XFUNC-C/div[12]/div[8]/p[1]", "#XFUNC-C/div[12]/p[11]", "#XFUNC-C/div[12]/p[13]", "#XFUNC-C/div[12]/p[14]", "#XFUNC-C/div[12]/p[16]", "#XFUNC-C/div[12]/p[18]", "#XFUNC-C/div[12]/p[19]", "#XFUNC-C/div[12]/p[1]", "#XFUNC-C/div[12]/p[21]", "#XFUNC-C/div[12]/p[22]", "#XFUNC-C/div[12]/p[24]", "#XFUNC-C/div[12]/p[25]", "#XFUNC-C/div[12]/p[27]", "#XFUNC-C/div[12]/p[28]", "#XFUNC-C/div[12]/p[3]", "#XFUNC-C/div[12]/p[4]", "#XFUNC-C/div[12]/p[6]", "#XFUNC-C/div[12]/p[9]", "#XFUNC-C/div[13]/div[19]/p[1]", "#XFUNC-C/div[13]/p[10]", "#XFUNC-C/div[13]/p[12]", "#XFUNC-C/div[13]/p[13]", "#XFUNC-C/div[13]/p[15]", "#XFUNC-C/div[13]/p[20]", "#XFUNC-C/div[13]/p[22]", "#XFUNC-C/div[13]/p[24]", "#XFUNC-C/div[13]/p[26]", "#XFUNC-C/div[13]/p[28]", "#XFUNC-C/div[13]/p[2]", "#XFUNC-C/div[13]/p[3]", "#XFUNC-C/div[13]/p[4]", "#XFUNC-C/div[13]/p[6]", "#XFUNC-C/div[13]/p[8]", "#XFUNC-C/div[14]/p[1]", "#XFUNC-C/div[14]/p[2]", "#XFUNC-C/div[14]/p[4]", "#XFUNC-C/div[14]/p[6]", "#XFUNC-C/div[15]/div[1]/div[0]", "#XFUNC-C/div[15]/div[1]/p[3]", "#XFUNC-C/div[15]/div[1]/p[5]", "#XFUNC-C/div[15]/div[1]/p[6]", "#XFUNC-C/div[15]/div[1]/p[8]", "#XFUNC-C/div[15]/div[1]/p[9]", "#XFUNC-C/div[15]/div[2]/div[0]", "#XFUNC-C/div[15]/div[2]/p[1]", "#XFUNC-C/div[15]/div[2]/p[3]", "#XFUNC-C/div[15]/div[2]/p[5]", "#XFUNC-C/div[16]/div[1]/div[0]", "#XFUNC-C/div[16]/div[2]/div[0]", "#XFUNC-C/div[16]/div[2]/p[1]", "#XFUNC-C/div[16]/div[2]/p[3]", "#XFUNC-C/div[16]/div[2]/p[5]", "#XFUNC-C/div[16]/div[2]/p[6]", "#XFUNC-C/div[16]/div[2]/p[8]", "#XFUNC-C/div[17]/p[1]", "#XFUNC-C/div[17]/p[3]", "#XFUNC-C/div[17]/p[4]", "#XFUNC-C/div[18]/p[10]", "#XFUNC-C/div[18]/p[12]", "#XFUNC-C/div[18]/p[13]", "#XFUNC-C/div[18]/p[15]", "#XFUNC-C/div[18]/p[16]", "#XFUNC-C/div[18]/p[18]", "#XFUNC-C/div[18]/p[19]", "#XFUNC-C/div[18]/p[1]", "#XFUNC-C/div[18]/p[20]", "#XFUNC-C/div[18]/p[3]", "#XFUNC-C/div[18]/p[4]", "#XFUNC-C/div[18]/p[6]", "#XFUNC-C/div[18]/p[7]", "#XFUNC-C/div[19]/p[10]", "#XFUNC-C/div[19]/p[1]", "#XFUNC-C/div[19]/p[2]", "#XFUNC-C/div[19]/p[4]", "#XFUNC-C/div[19]/p[6]", "#XFUNC-C/div[19]/p[7]", "#XFUNC-C/div[19]/p[8]", "#XFUNC-C/div[19]/p[9]", "#XFUNC-C/div[1]/dl[0]/dt[0]", "#XFUNC-C/div[1]/dl[0]/dt[10]", "#XFUNC-C/div[1]/dl[0]/dt[12]", "#XFUNC-C/div[1]/dl[0]/dt[13]", "#XFUNC-C/div[1]/dl[0]/dt[14]", "#XFUNC-C/div[1]/dl[0]/dt[15]", "#XFUNC-C/div[1]/dl[0]/dt[1]", "#XFUNC-C/div[1]/dl[0]/dt[2]", "#XFUNC-C/div[1]/dl[0]/dt[3]", "#XFUNC-C/div[1]/dl[0]/dt[4]", "#XFUNC-C/div[1]/dl[0]/dt[5]", "#XFUNC-C/div[1]/dl[0]/dt[6]", "#XFUNC-C/div[1]/dl[0]/dt[7]", "#XFUNC-C/div[1]/dl[0]/dt[8]", "#XFUNC-C/div[1]/dl[0]/dt[9]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[20]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[20]/p[2]", "#XFUNC-C/div[20]/p[4]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[0]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[1]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[2]", "#XFUNC-C/div[5]/div[4]/ol[0]/li[3]", "#XFUNC-C/div[5]/div[9]/h3[0]", "#XFUNC-C/div[5]/div[9]/p[1]", "#XFUNC-C/div[5]/p[12]", "#XFUNC-C/div[5]/p[14]", "#XFUNC-C/div[5]/p[16]", "#XFUNC-C/div[5]/p[18]", "#XFUNC-C/div[5]/p[19]", "#XFUNC-C/div[5]/p[22]", "#XFUNC-C/div[5]/p[2]", "#XFUNC-C/div[5]/p[3]", "#XFUNC-C/div[5]/p[5]", "#XFUNC-C/div[5]/p[6]", "#XFUNC-C/div[5]/p[7]", "#XFUNC-C/div[5]/p[8]", "#XFUNC-C/div[6]/div[13]/h3[0]", "#XFUNC-C/div[6]/div[13]/p[1]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[0]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/tbody[2]/tr[3]/td[2]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[0]", "#XFUNC-C/div[6]/div[21]/div[1]/table[0]/thead[1]/tr[0]/th[1]", "#XFUNC-C/div[6]/div[21]/p[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[0]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[1]", "#XFUNC-C/div[6]/div[4]/ul[0]/li[2]", "#XFUNC-C/div[6]/p[10]", "#XFUNC-C/div[6]/p[11]", "#XFUNC-C/div[6]/p[12]", "#XFUNC-C/div[6]/p[14]", "#XFUNC-C/div[6]/p[16]", "#XFUNC-C/div[6]/p[17]", "#XFUNC-C/div[6]/p[19]", "#XFUNC-C/div[6]/p[20]", "#XFUNC-C/div[6]/p[20]/span[2]/span[0]", "#XFUNC-C/div[6]/p[23]", "#XFUNC-C/div[6]/p[2]", "#XFUNC-C/div[6]/p[3]", "#XFUNC-C/div[6]/p[5]", "#XFUNC-C/div[6]/p[7]", "#XFUNC-C/div[6]/p[8]", "#XFUNC-C/div[7]/p[10]", "#XFUNC-C/div[7]/p[13]", "#XFUNC-C/div[7]/p[16]", "#XFUNC-C/div[7]/p[17]", "#XFUNC-C/div[7]/p[18]", "#XFUNC-C/div[7]/p[1]", "#XFUNC-C/div[7]/p[20]", "#XFUNC-C/div[7]/p[3]", "#XFUNC-C/div[7]/p[5]", "#XFUNC-C/div[7]/p[6]", "#XFUNC-C/div[7]/p[7]", "#XFUNC-C/div[7]/p[8]", "#XFUNC-C/div[7]/p[9]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[0]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[1]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[2]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[3]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[4]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[5]", "#XFUNC-C/div[8]/div[3]/ul[0]/li[6]", "#XFUNC-C/div[8]/p[1]", "#XFUNC-C/div[8]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[11]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[1]/p[2]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[3]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[5]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[7]/p[0]", "#XFUNC-C/div[9]/div[5]/dl[0]/dd[9]/p[0]", "#XFUNC-C/div[9]/div[6]/h3[0]", "#XFUNC-C/div[9]/div[6]/p[1]", "#XFUNC-C/div[9]/p[1]", "#XFUNC-C/div[9]/p[2]", "#XFUNC-C/div[9]/p[4]", "#XFUNC-C/div[9]/p[7]", "#XFUNC-C/div[9]/p[8]", "#XFUNC-C/p[3]"]}], "language": "zh", "original_text": {"/versions/18/description/0": "dynamically-loaded C functions", "/versions/18/facts/0/label": "Kind", "/versions/18/facts/0/value": "Native function language", "/versions/18/facts/1/label": "Trusted", "/versions/18/facts/2/label": "Validator"}, "fallback_fields": [], "source_language": "en", "original_snapshot_sha256": "126e9ec2b5157e7be6f2d1aaace3449ca213b73b9f2a7d82748ff9e6afc13a05"}, "comparison_data": {"kind": "Native function language", "handler": "", "trusted": "f", "validator": "fmgr_c_validator"}, "comparison_hash": "e8a219c1a26602affef41a21da26d099cf721ba42739cb7b056898c9e2d6fbe6", "manual_language": "zh"}, "comparison": {"left": "17", "right": "18", "status": "unchanged", "diff": ""}}