Обсуждение: PostgreSQL C Language Extension with C++ Code
Hi, I've searched information about my problem in the archives and on the internet, but it didn't help. I have this small myfunc.cpp 1: #include <postgres.h> 2: #include <utils/rel.h> 3: #include <postgres.h> 4: #include <fmgr.h> 5: #include <utils/array.h> 6: #include <utils/builtins.h> 7: #include <catalog/pg_type.h> 8: #include <string> 9: #include <vector> 10: #include <stdlib.h> 11: #include <stdint.h> 12: #include <iostream> 13: #include <fstream> 14: #include <seal/seal.h> // external compiled c++ library linked on running 'make' 15: 16: #ifdef PG_MODULE_MAGIC 17: PG_MODULE_MAGIC; 18: #endif 19: 20: Datum sum_of_numbers(PG_FUNCTION_ARGS); 21: PG_FUNCTION_INFO_V1(sum_of_numbers); 22: 23: extern "C" { 24: int64_t sum_of_numbers(){ 25: std::vector<int64_t> numbers {23, 445, 64}; 26: auto sum = 0; 27: for (auto &item : numbers){ 28: sum += item; 29: } 30: return sum; 31: } 32: } And I compile without any problem suing this Makefiles: 1: MODULES = myfunc 2: 3: PG_CONFIG = /usr/pgsql-10/bin/pg_config 4: PGXS = $(shell $(PG_CONFIG) --pgxs) 5: INCLUDEDIR = $(shell $(PG_CONFIG) --includedir-server) 6: INCLUDE_SEAL = /usr/local/include/seal 7: INCLUDE_SEAL_LIB = /usr/local/lib/libseal.a 8: INCLUDE_CPPCODEC = /usr/local/include/cppcodec 9: #CFLAGS = -std=c11 10: #CFLAGS = --std=c++14 -fPIC -Wall -Werror -g3 -O0 11: include $(PGXS) 12: myfunc.so: myfunc.o 13: g++ -shared -o myfunc.so myfunc.o 14: 16: myfunc.o: myfunc.cpp 17: g++ --std=c++17 -fPIC -Wall -Werror -g3 -O0 -o myfunc.o -c myfunc.cpp -I$(INCLUDEDIR) -L$(INCLUDE_SEAL_LIB) -I$(INCLUDE_SEAL) -I$(INCLUDE_CPPCODEC) 18: After copying the myfunc.so file to the PostgreSQL lib folder and executing: 1: CREATE OR REPLACE FUNCTION 2: sum_of_numbers() RETURNS integer AS 'myfunc' 3: LANGUAGE C STRICT; I get this error: *ERROR: incompatible library "/usr/pgsql-10/lib/myfunc.so": missing magic block HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro. SQL state: XX000* I've added the files and line numbers for an easier discussion. Thanks a lot, Tal myfunc.cpp <http://www.postgresql-archive.org/file/t351748/myfunc.cpp> Makefiles.Makefiles <http://www.postgresql-archive.org/file/t351748/Makefiles.Makefiles> -- Sent from: http://www.postgresql-archive.org/PostgreSQL-general-f1843780.html
TalGloz <glozmantal@gmail.com> writes: > I've searched information about my problem in the archives and on the > internet, but it didn't help. I have this small myfunc.cpp > [ that doesn't work ] > 16: #ifdef PG_MODULE_MAGIC > 17: PG_MODULE_MAGIC; > 18: #endif Hmm ... don't use an #ifdef there. If you don't have the macro defined, you want to fail, not silently build an extension without it. It's possible you need extern "C" { ... } around the macro, too. regards, tom lane
Hi, On Sun, Aug 12, 2018 at 12:05 PM, TalGloz <glozmantal@gmail.com> wrote: > Hi, > > I've searched information about my problem in the archives and on the > internet, but it didn't help. I have this small myfunc.cpp > > 1: #include <postgres.h> > 2: #include <utils/rel.h> > 3: #include <postgres.h> > 4: #include <fmgr.h> > 5: #include <utils/array.h> > 6: #include <utils/builtins.h> > 7: #include <catalog/pg_type.h> > 8: #include <string> > 9: #include <vector> > 10: #include <stdlib.h> > 11: #include <stdint.h> > 12: #include <iostream> > 13: #include <fstream> > 14: #include <seal/seal.h> // external compiled c++ library linked on > running 'make' > 15: > 16: #ifdef PG_MODULE_MAGIC I think you're missing "n" here. Should be: #ifndef PG_MODULE_MAGIC . Thank you. > 17: PG_MODULE_MAGIC; > 18: #endif > 19: > 20: Datum sum_of_numbers(PG_FUNCTION_ARGS); > 21: PG_FUNCTION_INFO_V1(sum_of_numbers); > 22: > 23: extern "C" { > 24: int64_t sum_of_numbers(){ > 25: std::vector<int64_t> numbers {23, 445, 64}; > 26: auto sum = 0; > 27: for (auto &item : numbers){ > 28: sum += item; > 29: } > 30: return sum; > 31: } > 32: } > > And I compile without any problem suing this Makefiles: > > 1: MODULES = myfunc > 2: > 3: PG_CONFIG = /usr/pgsql-10/bin/pg_config > 4: PGXS = $(shell $(PG_CONFIG) --pgxs) > 5: INCLUDEDIR = $(shell $(PG_CONFIG) --includedir-server) > 6: INCLUDE_SEAL = /usr/local/include/seal > 7: INCLUDE_SEAL_LIB = /usr/local/lib/libseal.a > 8: INCLUDE_CPPCODEC = /usr/local/include/cppcodec > 9: #CFLAGS = -std=c11 > 10: #CFLAGS = --std=c++14 -fPIC -Wall -Werror -g3 -O0 > 11: include $(PGXS) > 12: myfunc.so: myfunc.o > 13: g++ -shared -o myfunc.so myfunc.o > 14: > 16: myfunc.o: myfunc.cpp > 17: g++ --std=c++17 -fPIC -Wall -Werror -g3 -O0 -o myfunc.o -c > myfunc.cpp -I$(INCLUDEDIR) -L$(INCLUDE_SEAL_LIB) -I$(INCLUDE_SEAL) > -I$(INCLUDE_CPPCODEC) > 18: > > After copying the myfunc.so file to the PostgreSQL lib folder and executing: > > 1: CREATE OR REPLACE FUNCTION > 2: sum_of_numbers() RETURNS integer AS 'myfunc' > 3: LANGUAGE C STRICT; > > I get this error: > *ERROR: incompatible library "/usr/pgsql-10/lib/myfunc.so": missing magic > block > HINT: Extension libraries are required to use the PG_MODULE_MAGIC macro. > SQL state: XX000* > > I've added the files and line numbers for an easier discussion. > > Thanks a lot, > Tal > > myfunc.cpp <http://www.postgresql-archive.org/file/t351748/myfunc.cpp> > Makefiles.Makefiles > <http://www.postgresql-archive.org/file/t351748/Makefiles.Makefiles> > > > > -- > Sent from: http://www.postgresql-archive.org/PostgreSQL-general-f1843780.html >
OK now I have this code: 1: extern "C" { // The C header should go here 2: #include <postgres.h> 3: #include <utils/rel.h> 4: #include <fmgr.h> 5: #include <utils/array.h> 6: #include <utils/builtins.h> 7: #include <catalog/pg_type.h> 8: #include <stdlib.h> 9: #include <stdint.h> 10: 11: PG_MODULE_MAGIC; 12: } 13: 14: // CPP header without extern "C" 15: #include <string> 16: #include <vector> 17: #include <iostream> 18: #include <fstream> 19: #include <seal/seal.h> // external compiled c++ library linked on running 'make' 20: 21: Datum sum_of_numbers(PG_FUNCTION_ARGS); 22: PG_FUNCTION_INFO_V1(sum_of_numbers); 33: 34: extern "C" { // CPP function 35: int64_t sum_of_numbers(){ 36: std::vector<int64_t> numbers {23, 445, 64}; 37: auto sum = 0; 38: for (auto &item : numbers){ 39: sum += item; 40: } 41: return sum; 42: } 43: } The error this time for PostgreSQL is: *ERROR: could not find function information for function "sum_of_numbers" HINT: SQL-callable functions need an accompanying PG_FUNCTION_INFO_V1(funcname). SQL state: 42883* Thanks, Tal -- Sent from: http://www.postgresql-archive.org/PostgreSQL-general-f1843780.html
TalGloz <glozmantal@gmail.com> writes: > The error this time for PostgreSQL is: > *ERROR: could not find function information for function "sum_of_numbers" > HINT: SQL-callable functions need an accompanying > PG_FUNCTION_INFO_V1(funcname). > SQL state: 42883* Probably need extern "C" around the PG_FUNCTION_INFO_V1 macro, too. Both those macros produce C function definitions under the hood, and said functions need to not be name-mangled by C++. regards, tom lane
I did it with the macros extern "C" { Datum sum_of_numbers(PG_FUNCTION_ARGS); PG_FUNCTION_INFO_V1(sum_of_numbers); } But now my compiler throws some other errors when running make: g++ --std=c++17 -fPIC -Wall -Werror -g3 -O0 -o myfunc.o -c myfunc.cpp -I/usr/pgsql-10/include/server -L"/usr/local/lib/libseal.a" -I"/usr/local/include/seal" -I"/usr/local/include/cppcodec" myfunc.cpp:29:10: error: conflicting declaration of C function ‘int64_t sum_of_numbers()’ int64_t sum_of_numbers(){ ^~~~~~~~~~~~~~ In file included from /usr/pgsql-10/include/server/utils/array.h:64, from /usr/pgsql-10/include/server/utils/acl.h:38, from /usr/pgsql-10/include/server/catalog/objectaddress.h:18, from /usr/pgsql-10/include/server/catalog/pg_publication.h:21, from /usr/pgsql-10/include/server/utils/rel.h:21, from myfunc.cpp:3: myfunc.cpp:25:21: note: previous declaration ‘Datum sum_of_numbers(FunctionCallInfo)’ PG_FUNCTION_INFO_V1(sum_of_numbers); ^~~~~~~~~~~~~~ /usr/pgsql-10/include/server/fmgr.h:374:14: note: in definition of macro ‘PG_FUNCTION_INFO_V1’ extern Datum funcname(PG_FUNCTION_ARGS); \ ^~~~~~~~ make: *** [Makefile:16: myfunc.o] Error 1 Why is it so hard to use C++ with PostgerSQL for a C extension? :) Regards, Tal -- Sent from: http://www.postgresql-archive.org/PostgreSQL-general-f1843780.html
вс, 12 авг. 2018 г. в 21:40, TalGloz <glozmantal@gmail.com>: > > I did it with the macros > > extern "C" { > Datum sum_of_numbers(PG_FUNCTION_ARGS); > PG_FUNCTION_INFO_V1(sum_of_numbers); > } > > But now my compiler throws some other errors when running make: > > g++ --std=c++17 -fPIC -Wall -Werror -g3 -O0 -o myfunc.o -c myfunc.cpp > -I/usr/pgsql-10/include/server -L"/usr/local/lib/libseal.a" > -I"/usr/local/include/seal" -I"/usr/local/include/cppcodec" > myfunc.cpp:29:10: error: conflicting declaration of C function ‘int64_t > sum_of_numbers()’ > int64_t sum_of_numbers(){ > ^~~~~~~~~~~~~~ > In file included from /usr/pgsql-10/include/server/utils/array.h:64, > from /usr/pgsql-10/include/server/utils/acl.h:38, > from > /usr/pgsql-10/include/server/catalog/objectaddress.h:18, > from > /usr/pgsql-10/include/server/catalog/pg_publication.h:21, > from /usr/pgsql-10/include/server/utils/rel.h:21, > from myfunc.cpp:3: > myfunc.cpp:25:21: note: previous declaration ‘Datum > sum_of_numbers(FunctionCallInfo)’ > PG_FUNCTION_INFO_V1(sum_of_numbers); > ^~~~~~~~~~~~~~ > /usr/pgsql-10/include/server/fmgr.h:374:14: note: in definition of macro > ‘PG_FUNCTION_INFO_V1’ > extern Datum funcname(PG_FUNCTION_ARGS); \ > ^~~~~~~~ > make: *** [Makefile:16: myfunc.o] Error 1 > > Why is it so hard to use C++ with PostgerSQL for a C extension? :) It is not.
TalGloz <glozmantal@gmail.com> writes: > But now my compiler throws some other errors when running make: > myfunc.cpp:29:10: error: conflicting declaration of C function ‘int64_t > sum_of_numbers()’ > int64_t sum_of_numbers(){ > ^~~~~~~~~~~~~~ Well, yeah, you forgot to repeat the argument list here. For that matter, spelling Datum as int64_t is a recipe for trouble, even if it works on some particular platform. Should be Datum sum_of_numbers(PG_FUNCTION_ARGS) { ... > Why is it so hard to use C++ with PostgerSQL for a C extension? :) Probably because you've failed to break your bad C++ habits. regards, tom lane
Let me see if I understood you correctly. I cant have a code like this: extern "C" { int sum_of_numbers(){ std::vector<int> numbers {23, 445, 64}; int sum = 0; for (auto &item : numbers){ sum += item; } return sum; } } And I have to declare my function with inside the Datum sum_of_numbers(PG_FUNCTION_ARGS){ // function code here } Sorry for the log mails. I'm having problems to understand, how to change the construction of myfunc.cpp to run the code. -- Sent from: http://www.postgresql-archive.org/PostgreSQL-general-f1843780.html
OK It worked. This is how I did it, hopefully it is right extern "C" { #include <postgres.h> #include <utils/rel.h> #include <fmgr.h> #include <utils/array.h> #include <utils/builtins.h> #include <catalog/pg_type.h> #include <stdlib.h> #include <stdint.h> PG_MODULE_MAGIC; } #include <string> #include <vector> #include <iostream> #include <fstream> #include <seal/seal.h> // external compiled c++ library linked on running 'make' extern "C" { Datum sum_of_numbers(PG_FUNCTION_ARGS){ std::vector<int> numbers {23, 445, 64}; int sum = 0; for (auto &item : numbers){ sum += item; } return sum; }; PG_FUNCTION_INFO_V1(sum_of_numbers); } I've managed to create and execute the function in my PostgreSQL database. So basically I can execute any CPP code as long as I declare my functions like this: extern "C" { Datum function_name(PG_FUNCTION_ARGS){ // CPP code here }; PG_FUNCTION_INFO_V1(function_name); } In addition tho thath, all the C headers should be * inside a extern "C" { }* block and all the CPP headers *outside the extern "C" { }* block, did I get it right? Thanks, Tal -- Sent from: http://www.postgresql-archive.org/PostgreSQL-general-f1843780.html