1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
|
/*
* Copyright (c) 2023 Attila Szakacs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As an additional exemption you are allowed to compile & link against the
* OpenSSL libraries as published by the OpenSSL project. See the file
* COPYING for details.
*
*/
/*
* C++ compat helper headers: "compat/cpp-start.h" and "compat/cpp-end.h"
*
* Starting your C++ header with #include "compat/cpp-start.h" and ending it
* with #include "compat/cpp-end.h" helps you with two things:
* - You will be able to include C headers.
* - C files will be able to include your C++ header.
*
* Limitations:
* - Obviously you can only write code in your C++ header which is
* syntactically correct in a C code, so you cannot define classes, etc.
* Do these in either your .cpp file or in a separate .hpp file, which
* does not get included in your C code.
* - As we are not preparing each C header to be includable in C++ code,
* but we are trying to include them with these helpers on the call site,
* we cannot be sure that any additional C header include will work.
* This adds a level of uncertainty to developing a plugin in C++.
*
* If you find a C header that cannot be imported to C++ with these helpers,
* please try to fix those headers first. If it is not possible, extend this
* file with a workaround so others do not run into that issue again.
*
* Best practices:
* - Minimize the C++ code in your plugin, if you can write and build/link
* something as C code, do so, for example boilerplates: parser.{c,h}
* and plugin.c. This minimizes the chance of including an incompatible
* C header.
* - Build/link the C++ code as C++ separately and link to that from your
* C lib. In case your C++ library is static, add the following to the
* the C lib to force linking against the appropriate C++ standard
* library (libc++, libstdc++):
* nodist_EXTRA_*_SOURCES = force-cpp-linker-with-default-stdlib.cpp
* - In your C++ code it is not possible to derive from a C class in the
* usual C way by adding a super field and filling its free_fn, because
* we do our own reference counting and freeing logic and we cannot rely
* on the casting trick of struct packing. You can create a struct
* in the usual C inheritance way and have a pointer to your C++ class
* in it and you can store a pointer to this struct in your C++ class as
* super, so you can access its fields. You can set the necessary virtual
* functions with wrapper functions of your real C++ functions in the
* ctor of the C style "class" == struct.
*
* Header ordering:
* - syslog-ng.h needs to come first even in cpp/hpp files. You don't
* need cpp-start/end wrapper around syslog-ng.h. This include can
* happen indirectly, e.g. if you include any other header that should
* take care of syslog-ng.h
*
* - syslog-ng.h will include glib too, which is also C++ safe. This is
* needed as some constructs in glib only work if it is outside of an
* extern "C" block.
*
* - Use the usual header ordering conventions, e.g. include the closest
* header first (e.g. the one associated with your module) and then
* iterate to furthest. This ensures that each header is actually
* standalone and includes all its dependencies.
*
* - If you use a .hpp file, include .h from it and make sure the .h
* includes syslog-ng.h and includes all other .h files by wrapping them
* using cpp-start/end.h as needed. This takes care of the first rule.
*
* - In your .cpp files, include the .hpp file but not the .h file which is
* already included.
*
* You can see an example usage of the C++ plugin support at:
* modules/examples/sources/random-choice-generator
*/
#ifdef __cplusplus
#define this this_
extern "C" {
#endif
|