CREATE FUNCTION c_overpaid(emp, integer) RETURNS boolean
AS 'os_libpath', 'c_funcname'
LANGUAGE C STRICT;
文档中提到两种调用习惯 V0 和 V1,从代码里边看,V0已经不再支持。
这里不去考虑函数定义方法,着重看 MAGIC 定义,相信很多朋友遇到过这个错误:
ereport(ERROR,
(errmsg("incompatible library \"%s\": missing magic block",
libname),
errhint("Extension libraries are required to use the PG_MODULE_MAGIC macro.")));
这是没有在外部库里边引入 magic data 引起的,它定义在 fmgr.h 中:
/* The actual data block contents */
#define PG_MODULE_MAGIC_DATA \
{ \
sizeof(Pg_magic_struct), \
PG_VERSION_NUM / 100, \
FUNC_MAX_ARGS, \
INDEX_MAX_KEYS, \
NAMEDATALEN, \
FLOAT4PASSBYVAL, \
FLOAT8PASSBYVAL \
}
/*
* Declare the module magic function. It needs to be a function as the dlsym
* in the backend is only guaranteed to work on functions, not data
*/
typedef const Pg_magic_struct *(*PGModuleMagicFunction) (void);
#define PG_MAGIC_FUNCTION_NAME Pg_magic_func
#define PG_MAGIC_FUNCTION_NAME_STRING "Pg_magic_func"
#define PG_MODULE_MAGIC \
extern PGDLLEXPORT const Pg_magic_struct *PG_MAGIC_FUNCTION_NAME(void); \
const Pg_magic_struct * \
PG_MAGIC_FUNCTION_NAME(void) \
{ \
static const Pg_magic_struct Pg_magic_data = PG_MODULE_MAGIC_DATA; \
return &Pg_magic_data; \
} \
extern int no_such_variable
载入外部库时,首先检查有没有 "Pg_magic_func" 函数,如果有将它的返回值与当前数据库内核定义作比较,如果不符合就会报错,具体逻辑请看 src/backend/utils/fmgr/dfmgr.c
中定义的 internal_load_library 函数
源代码。