PG_GETARG_DATUM(0);
/* we have one dimension */
ndims = 1;
/* and one element */
dims[0] = 1;
/* and lower bound is 1 */
lbs[0] = 1;
/* get required info about the element type */
get_typlenbyvalalign(element_type, &typlen, &typbyval, &typalign);
/* now build the array */
result = construct_md_array(&element, &isnull, ndims, dims, lbs,
element_type, typlen, typbyval, typalign);
PG_RETURN_ARRAYTYPE_P(result);
}
</programlisting>
</para>
<para>
The following command declares the function
<function>make_array</function> in SQL:
<programlisting>
CREATE FUNCTION make_array(anyelement) RETURNS anyarray
AS '<replaceable>DIRECTORY</replaceable>/funcs', 'make_array'
LANGUAGE C IMMUTABLE;
</programlisting>
</para>
<para>
There is a variant of polymorphism that is only available to C-language
functions: they can be declared to take parameters of type
<literal>"any"</literal>. (Note that this type name must be double-quoted,
since it's also an SQL reserved word.) This works like
<type>anyelement</type> except that it does not constrain different
<literal>"any"</literal> arguments to be the same type, nor do they help
determine the function's result type. A C-language function can also
declare its final parameter to be <literal>VARIADIC "any"</literal>. This will
match one or more actual arguments of any type (not necessarily the same
type). These arguments will <emphasis>not</emphasis> be gathered into an array
as happens with normal variadic functions; they will just be passed to
the function separately. The <function>PG_NARGS()</function> macro and the
methods described above must be used to determine the number of actual
arguments and their types when using this feature. Also, users of such
a function might wish to use the <literal>VARIADIC</literal> keyword in their
function call, with the expectation that the function would treat the
array elements as separate arguments. The function itself must implement
that behavior if wanted, after using <function>get_fn_expr_variadic</function> to
detect that the actual argument was marked with <literal>VARIADIC</literal>.
</para>
</sect2>
<sect2 id="xfunc-shared-addin">
<title>Shared Memory</title>
<sect3 id="xfunc-shared-addin-at-startup">
<title>Requesting Shared Memory at Startup</title>
<para>
Add-ins can reserve shared memory on server startup. To do so, the
add-in's shared library must be preloaded by specifying it in
<xref linkend="guc-shared-preload-libraries"/><indexterm><primary>shared_preload_libraries</primary></indexterm>.
The shared library should also register a
<literal>shmem_request_hook</literal> in its
<function>_PG_init</function> function. This
<literal>shmem_request_hook</literal> can reserve shared memory by
calling:
<programlisting>
void RequestAddinShmemSpace(Size size)
</programlisting>
Each backend should obtain a pointer to the reserved shared memory by
calling:
<programlisting>
void *ShmemInitStruct(const char *name, Size size, bool *foundPtr)
</programlisting>
If this function sets <literal>foundPtr</literal> to
<literal>false</literal>, the caller should proceed to initialize the
contents of the reserved shared memory. If <literal>foundPtr</literal>
is set to <literal>true</literal>, the shared memory was already
initialized by another backend, and the caller need not initialize
further.
</para>
<para>
To avoid race conditions, each backend should use the LWLock
<function>AddinShmemInitLock</function> when initializing its allocation
of shared memory, as shown here:
<programlisting>
static mystruct *ptr = NULL;
bool found;
LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE);