How to handle postgres redefinition of std::snprintf to pg_snprintf in C++ code

From: Vicky Vergara <vicky_vergara(at)hotmail(dot)com>
To: "pgsql-general(at)postgresql(dot)org" <pgsql-general(at)postgresql(dot)org>
Subject: How to handle postgres redefinition of std::snprintf to pg_snprintf in C++ code
Date: 2024-01-18 22:53:28
Message-ID: DM8P220MB0390EEBC5BD8065CB37C29DC8A712@DM8P220MB0390.NAMP220.PROD.OUTLOOK.COM
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

Hi all

I am the pgRouting extension main developer, and I came with an interesting problem.

We use boost::graph intensively on the C++ code
Currently, getting the data from the data base is done on the C code

I am working on moving code that reads data from postgres: code on a C function to a C++ function

This implies that postgres.h​ and several postgres server files need to be wrapped with extern

So a header file that has a function that will be linked as C will have the following code:

#ifdef __cplusplus
extern "C" {
#endif
#include <postgres.h>
#include <executor/spi.h>
...
}
#endif

But on port.h
https://doxygen.postgresql.org/port_8h_source.html

There are the following definitions

#define vsnprintf pg_vsnprintf
#define snprintf pg_snprintf
#define vsprintf pg_vsprintf
#define sprintf pg_sprintf
#define vfprintf pg_vfprintf
#define fprintf pg_fprintf
#define vprintf pg_vprintf

And for example:
std::sprintf and std::snprintf are defined on C++ cstdio:​
https://en.cppreference.com/w/cpp/header/cstdio
which pgROuting directly does not includes it but boost::graph does.

Because of that this kind of errors are appearing:

In file included from /Users/runner/work/pgrouting/pgrouting/src/dominator/lengauerTarjanDominatorTree_driver.cpp:45:
In file included from /Users/runner/work/pgrouting/pgrouting/include/cpp_common/basePath_SSEC.hpp:42:
In file included from /usr/local/include/boost/graph/adjacency_list.hpp:20:
...
In file included from /usr/local/include/boost/ ...
...
In file included from /usr/local/include/boost/exception/exception.hpp:9:
/usr/local/include/boost/assert/source_location.hpp:97:9: error: no member named 'pg_snprintf' in namespace 'std'; did you mean simply 'pg_snprintf'?
BOOST_ASSERT_SNPRINTF( buffer, ":%lu", ln );
[100%] Built target topologicalSort
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/local/include/boost/assert/source_location.hpp:81:53: note: expanded from macro 'BOOST_ASSERT_SNPRINTF'
[100%] Built target mincut
# define BOOST_ASSERT_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg)
^~~~~
/usr/local/include/postgresql(at)14/server/port.h:208:12: note: 'pg_snprintf' declared here
extern int pg_snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3, 4);
^

As a solution/workaround to that macro getting expanded into the C++ code, this looks to work

#ifdef __cplusplus
extern "C" {
#endif
#include <postgres.h>
#include <executor/spi.h>
...
extern "C" {
}
#endif

// undef what needs to be undefined from postgres define
#ifdef __cplusplus

#ifdef sprintf
#undef sprintf
#endif

#ifdef snprintf
#undef snprintf
#endif

...

#endif

Related message:
https://www.postgresql.org/message-id/flat/AM6PR0702MB37832527E6FADE9229CAF1CAAE0A0%40AM6PR0702MB3783.eurprd07.prod.outlook.com

Browse pgsql-general by date

  From Date Subject
Next Message Masahiko Sawada 2024-01-19 08:09:47 Re: Emitting JSON to file using COPY TO
Previous Message Antonin Bas 2024-01-18 21:32:14 Re: What should I expect when creating many logical replication slots?