2016-06-26 3 views
0

Ich versuche, sowohl eine externe PostgreSQL Funktion auf OSX 10.11 mit clang zu bauen und gcc, aber Link fehlgeschlagen mit den folgenden Fehlern:PostgreSQL externer C-Funktion Link fehlgeschlagen auf Mac OSX

c++ -I/usr/local/Cellar/postgresql/9.5.3/include/server -fpic -c ./main.c

c++ -shared -o ttt.dylib main.o 
Undefined symbols for architecture x86_64: 
    "_deconstruct_array", referenced from: 
    _psql_nearest in main.o 
    "_elog_finish", referenced from: 
    _psql_nearest in main.o 
    "_elog_start", referenced from: 
    _psql_nearest in main.o 
    "_get_typlenbyvalalign", referenced from: 
    _psql_nearest in main.o 
    "_pfree", referenced from: 
    _psql_nearest in main.o 
    "_pg_detoast_datum", referenced from: 
    _psql_nearest in main.o 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

Es sieht so aus, als müsste ich meine Bibliothek mit einigen PostgreSQL Bibliotheken verknüpfen. Was sind diese Bibliotheken?

main.cpp: 

extern "C" { 
    #include <postgres.h> 
    #include <fmgr.h> 
    #include <utils/array.h> 
    #include <utils/lsyscache.h> 
    #include <catalog/pg_type.h> 

    #ifdef PG_MODULE_MAGIC 
     PG_MODULE_MAGIC; 
    #endif 

    PG_FUNCTION_INFO_V1(psql_nearest); 
    Datum psql_nearest(PG_FUNCTION_ARGS) { 
     if(PG_ARGISNULL(0) || PG_ARGISNULL(1)) { 
      elog(ERROR, "DOC2VEC: NULL INPUT DATA"); 
      PG_RETURN_NULL(); 
     } 

     ArrayType *_docVector = PG_GETARG_ARRAYTYPE_P(0); 
     Oid elTypeVals = ARR_ELEMTYPE(_docVector); 
     if (elTypeVals != FLOAT4OID) { 
      elog(ERROR, "DOC2VEC: INVALID INPUT DATA TYPE"); 
      PG_RETURN_NULL(); 
     } 

     int16 typeLenVals = 0; 
     bool typeByValVals = false; 
     char typeAlignVals = char(0); 
     get_typlenbyvalalign(elTypeVals, &typeLenVals, &typeByValVals, &typeAlignVals); 

     Datum *inputVals; 
     bool *nullVals; 
     int nVals; 
     deconstruct_array(_docVector, elTypeVals, typeLenVals, typeByValVals, typeAlignVals, &inputVals, &nullVals, &nVals); 

     pfree(inputVals); 
     pfree(nullVals); 

     PG_RETURN_NULL(); 
    } 
} 
+0

Nur um 100% klar zu sein: Ihre Bearbeitung hat die Quellcodedatei von 'main.c' in' main.cpp' geändert, aber der 'cc' Befehl oben hat immer noch' main.c'. Das sollte auch 'main.cpp' sein, oder? Oder haben Sie nur den Namen geändert, um den 'externen 'C'-Teil zu erklären, aber der eigentliche Dateiname ist' main.c'. Das wird verwirrend sein. – Evert

+0

Versuchen Sie unter anderem, mit 'pgcommon' zu verlinken. 'pgfree lebt dort '. – Evert

+0

Ja, ich habe 'main.c' in' main.cpp' und 'cc' in' C++ 'geändert, um zu erklären, warum ich' extern "C" brauche. Ich versuchte (erfolglos), mit 'pgcommon',' pgtypes', 'pgport' und' libpq' zu verbinden –

Antwort

1

Dank PostgreSQL Entwickler verwendet wird, sie erklärte mir den Unterschied in Linux und OSX Anbindung externer Funktionen. Anstatt -shared benötigen Sie -bundle -bundle_loader /path/to/postgres, und es gibt einige andere Linker-Flags, die auch ratsam sind. Auch PostgreSQL erwartet die Dateierweiterung für ladbare Module .so sogar auf OSX.

Es ist normalerweise besser, PGXS anstelle von Erweiterungen zu verwenden, um solche Details für sich selbst zu lernen. Oder Sie können Krippe von einer der Erweiterungen in der Quelltextbaum contrib/ .

0

Wenn Sie Link benötigen, müssen Sie die -L Flag den Linker auf den Weg zu zeigen, wo die Postgres-Bibliotheken befinden (Linker Äquivalent des -I Compiler-Flag). und das Flag -l, um die Bibliotheken tatsächlich zu verknüpfen (eine für jede Bibliothek); der Bibliotheksname ohne das Präfix lib und ohne die Erweiterung.

In Ihrem Fall etwas entlang der Linien von -L/usr/local/Cellar/postgresql/9.5.3/lib -lpostgres

(Es gibt eine Vielzahl von Bibliothek Dateien in diesem Verzeichnis, -lpg versuchen, mit zu beginnen
Der Verweis auf _pfree in der Fehlermeldung auch vorschlagen, pgcommon zu verknüpfen. , die enthält die Implementierung von pgree (zumindest bei der Verwendung von nm libpgcommon.a). )


möglicherweise möchten Sie auf ein bisschen mehr lesen Kompilieren und Verknüpfen im Allgemeinen; Sie tun das Richtige für die Kompilierung mit der -I Flagge, aber seltsamerweise dann verpassen Sie die Verknüpfung Schritt. Und das Lernen über make und Makefiles wird sich als nützlich erweisen.
Ich verstehe auch nicht die Teil für eine .c Datei, die eindeutig eine C-only-Datei ist. extern "C" in der Regel in C++ Dateien für die Kompatibilität mit C.

+0

Danke, aber das Problem ist, dass ich unter Linux keine Bibliotheken brauche, um diese externe PostgreSQL-C-Funktion zu verbinden. –

+0

Ich bin genug Erfahrung in make-Tools usw., meine Frage ist, welche Bibliotheken brauche ich auf OSX für die erfolgreiche Verknüpfung einer externen PostgreSQL-C-Funktion. Der externe Abschnitt "C" wird benötigt, da ich C++ - Code innerhalb der psql_nearest-Funktion verwende. –

+0

In diesem Fall sollten Sie ein wenig suchen, um die Bibliotheken zu finden. Unter Linux benötigen Sie keine Linkerpfad-Flags, da sich die Dateien an Standardspeicherorten befinden. Sie benötigen jedoch auch das Flag "-l", um die Postgres-Bibliothek zu verknüpfen. Wenn Sie das nicht brauchen, gibt es etwas Fischiges (oder eine Nicht-Standard-Einstellung): selbst die Standard-Mathematik-Bibliothek erfordert -lm unter Linux. – Evert