Useful documentation:
For a function foo that is to be coded with c++ and is going to return sets I have the following files:
- foo.c
- foo_driver.h
- foo_driver.cpp
foo.c
follows the "35.9.9. Returning Sets (A complete example of a simple SRF returning a composite type looks like)" except that we call a static function that is going to do some stuff (mostly read more data) before calling the actual c++ function.
static process ( char* a, bool b, bool c, mystruct* result_tuples, int result_count) {
<maybe some checking or conversions here of a, b, & c>
call_cpp_function( a1, b1, c1, result_tuples, result_count )
}
PG_FUNCTION_INFO_V1(foo);
Datum
foo(PG_FUNCTION_ARGS) {
...
process(
pgr_text2char(PG_GETARG_TEXT_P(0)),
PG_GETARG_BOOL(1),
PG_GETARG_BOOL(2),
&result_tuples,
&result_count);
...
} // end of first call
...
if (call_cntr < max_calls) {
...
else {
free(result_tuples);
SRF_RETURN_DONE(funcctx);
}
};
foo_driver
Has the definition of the C++ function that is going to be used on the C code and on the C++ code
#ifdef __cplusplus
extern "C" {
#endif
void call_cpp_function( <parameters > );
#ifdef __cplusplus
}
#endif
foo_driver.cpp
has the actual cpp code of the function "call_cpp_function"
non of the postgres files are to be included here, and of course you can include more c++ files here.
Particular rules:
- don't forget the try/catch or you can crash the server
- as soon as possible convert the C arrays to C++ containers
- don't use pointers on the C++ code except
- when creating the resulting C array (remember my example returns a set)
- and dont forget the "free" statement after the last call is done
for example
#include < vector >
#include < deque >
#include "myclass.h"
void call_cpp_function( <parameters > ) {
try {
<process>
// use malloc to prepare the C array
} catch( .. ) {
// do cleanup
}
}
Note: things not covered in this answer: compiling, linking, adding as an extension.