PostgreSQL расширение с использованием GEOS и PostGIS - неопределенный символ: lwgeom_geos_error - PullRequest
1 голос
/ 10 февраля 2020

Я пытался написать какое-то расширение PostgreSQL, просто простую функцию, основанную на этом учебнике . Это работает, но затем я хочу написать расширение, которое использует некоторый код GEOS. Поэтому я написал функцию в соответствии с функцией Postgis ST_RelateMatch (но для более чем одного параметра шаблона), но у меня возникла проблема во время компиляции (возможно, со связыванием).

Это моя функция, написанная в C:

#include "postgres.h"
#include "fmgr.h"
#include "funcapi.h"
#include "utils/builtins.h"

// here I had to add path to headers because I got fatal error: lwgeom_geos.h: No such file or directory
#include "./postgis-3.0.0/liblwgeom/lwgeom_geos.h"
#include "./postgis-3.0.0/libpgcommon/lwgeom_pg.h"

#include <string.h>
#include <assert.h>

/* #define POSTGIS_DEBUG_LEVEL 4 */

/* My RelateMatchFunction */
PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(myrelatematch);

Datum myrelatematch(PG_FUNCTION_ARGS)
{
    char *mat, *pat;
    text *mat_text, *pat_text;
    int result, arg;

    mat_text = (PG_GETARG_TEXT_P(0));
    mat = text_to_cstring(mat_text);

    initGEOS(lwpgnotice, lwgeom_geos_error);

    for (arg=1; arg < PG_NARGS(); arg++)
    {
        if (!PG_ARGISNULL(arg))
        {
            pat_text = (PG_GETARG_TEXT_P(arg));
            pat = text_to_cstring(pat_text);

            result = GEOSRelatePatternMatch(mat, pat);
            if (result == 2)
            {
                lwfree(mat); lwfree(pat);
                lwpgerror("GEOSRelatePatternMatch: %s", lwgeom_geos_errmsg);
                PG_RETURN_NULL();
            } else if (result == 1)
            {
                lwfree(mat); lwfree(pat);
                PG_RETURN_BOOL(result);
            }
        }
    }
    PG_RETURN_BOOL(0);
}

Тогда я использовал Makefile из учебника:

MODULES = myrelatematch
EXTENSION = myrelatematch
DATA = myrelatematch--0.0.1.sql
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

И это мой SQL код:

CREATE OR REPLACE FUNCTION
myrelatematch(text,variadic text[]) RETURNS int AS 'MODULE_PATHNAME','myrelatematch'
LANGUAGE C STRICT;

Теперь, если я запускаю make в Ubuntu 18.04, ошибки нет. Он создает общий объект, если я запускаю sudo make install, ошибки нет, но если я запускаю CREATE EXTENSION myrelatematch в базе данных, я получаю эту ошибку:

ERROR:  could not load library "/usr/lib/postgresql/11/lib/myrelatematch.so": /usr/lib/postgresql/11/lib/myrelatematch.so: undefined symbol: lwgeom_geos_error

Я работаю Ubuntu 18.04 Все библиотеки для Postgis находятся на сервере (я могу скомпилировать Postgis из исходного кода). Postgresql версия - 11,6 .

У меня нет опыта, и я всегда нахожу проблему с компиляцией какой-то большей части программного обеспечения. Я предположил, что есть проблема со связыванием библиотек, но после всего дня отладки мне нужна помощь.

РЕДАКТИРОВАТЬ

Если я скопирую команду g cc и добавлю -Wl,--no-undefined Я получаю ошибки от компоновщика:

/home/username/myrelatematch/myrelatematch.c:26: undefined reference to `pg_detoast_datum'
/home/username/myrelatematch/myrelatematch.c:27: undefined reference to `text_to_cstring'
/home/username/myrelatematch/myrelatematch.c:29: undefined reference to `lwgeom_geos_error'
/home/username/myrelatematch/myrelatematch.c:29: undefined reference to `lwpgnotice'
/home/username/myrelatematch/myrelatematch.c:29: undefined reference to `initGEOS'
/home/username/myrelatematch/myrelatematch.c:35: undefined reference to `pg_detoast_datum'
/home/username/myrelatematch/myrelatematch.c:36: undefined reference to `text_to_cstring'
/home/username/myrelatematch/myrelatematch.c:38: undefined reference to `GEOSRelatePatternMatch'
/home/username/myrelatematch/myrelatematch.c:46: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:46: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:41: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:41: undefined reference to `lwfree'
/home/username/myrelatematch/myrelatematch.c:42: undefined reference to `lwgeom_geos_errmsg'
/home/username/myrelatematch/myrelatematch.c:42: undefined reference to `lwpgerror'

Если я добавлю -L/home/username/myrelatematch/postgis-3.0.0/liblwgeom, изменений не будет, и ошибка та же.

Вот полный g cc команда:

gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -g -g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fno-omit-frame-pointer -fPIC -L/usr/lib/x86_64-linux-gnu -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -L/usr/lib/llvm-6.0/lib  -L/usr/lib/x86_64-linux-gnu/mit-krb5 -Wl,--as-needed -L/home/username/myrelatematch/postgis-3.0.0/liblwgeom -Wl,--no-undefined -shared -o myrelatematch.so myrelatematch.o

1 Ответ

0 голосов
/ 13 апреля 2020

На основании этих вопросов ( вопрос pgxs - связывание c -функций с внешними библиотеками и PGXS игнорирует SHLIB_LINK при связывании модулей ) Я нашел решение.

Вот пример Makefile со сторонними библиотеками

И мой Makefile для GEOS, LIBLWGEOM a LIBPGCOMMON библиотек:

EXTENSION = vectgen        
DATA = vectgen--0.0.1.sql  
OBJS = vectgen.o
MODULE_big = vectgen

# postgres build stuff
SHLIB_LINK = -lgeos_c -llwgeom -lpgcommon
PG_LDFLAGS += -L /home/username/CLionProjects/test_geos/libpgcommon
PG_CPPFLAGS = -I /home/username/CLionProjects/test_geos/libpgcommon
PG_CONFIG = pg_config
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

У меня есть изменения MODULES для MODULE_big, тогда SHLIB_LINK учитывается при компиляции, поэтому флаг -l работает для библиотек. После этого я копирую libpgcommon из PostGIS в свой проект и связываю его с PG_LDFLAGS.

...