Use macro define between module interface and implementation unit - c++

I have a module interface unit in a SomeModule.ixx file, with some functions prototypes generated using a preprocessor macro:
export module SomeModule;
#define GENERATED_FUNCTION(ret, name, ...) typedef ret name##_prototype(__VA_ARGS__); \
#define GENERATED_FUNCTIONS_LIST \
GENERATED_FUNCTION(void, some_function, int param1, double param2) \
GENERATED_FUNCTION(void, some_function2, int param1, float param2) \
GENERATED_FUNCTION(void, some_function3, int* param1, int** param2) \
GENERATED_FUNCTIONS_LIST
#undef GENERATED_FUNCTION
export struct SomeStruct {
void init();
#define GENERATED_FUNCTION(ret, name, ...) \
name##_prototype* name;
GENERATED_FUNCTIONS_LIST
#undef GENERATED_FUNCTION
};
and an implementation unit in SomeModuleImpl.cpp :
module SomeModule;
void SomeStruct::init() {
#define GENERATED_FUNCTION(ret, name, ...) \
name = NULL;
GENERATED_FUNCTIONS_LIST
#undef GENERATED_FUNCTION
}
I want to set some value for the methods in SomeStruct, again using the macro, however I'm getting this error in the module implementation:
E0020 identifier "GENERATED_FUNCTIONS_LIST" is undefined
Is there any way to share macro defines between module interface and implementation?

Is there any way to share macro defines between module interface and implementation?
Yes, the same one you used to use: a header file. Put your GENERATED_FUNCTIONS_LIST macro in a header file. This is pretty standard for X-macro-style code.
Modules don't include macros, so it doesn't change much of what you have to do there.

Related

Using a enum class from a c++ header in a c header

I am writing a c wrapper around a c++ library.
In the c++ there are enum classes used as types for function arguments.
How do I use theme correctly in the c header.
One ugly way would be to use int's in the c function and cast theme in the wrapper function to the enum type. But this gives the user of the c function no clue about the valid values, and it is really hard to check if the value is valid.
cpp header
namespace GPIO
{
enum class Directions
{
UNKNOWN,
OUT,
IN,
HARD_PWM
};
void setup(int channel, Directions direction, int initial = -1);
}
c wrapper header
int setup(int channel, int direction, int initial);
c wrapper code
int setup(int channel, int direction, int initial)
{
GPIO::setup(channel, static_cast<GPIO::Directions>(direction), initial);
return 0;
}
What would be a good way to give the user of the c functions the benefits of the enum classes in the c++ library. Because it is not my library, I would like to not change too much of the code in the library.
There would be the option to extract the enum classes to a different file and include it in the original header. But I don't know how to define it correctly, so I don't have to change the naming in the cpp library and still can use it in the c header.
You can not do it. It is impossible to use C++ features from C code. You are creating C wrapper for C++ function, why can not you create also C wrapper for enum? The only question is how to be sure that both enums have the same values. You can check it compile time after the small code change:
cpp header:
namespace GPIO
{
enum class Directions
{
UNKNOWN,
OUT,
IN,
HARD_PWM,
SIZE
};
}
c wrapper header:
enum GPIO_Directions
{
GPIO_Directions_UNKNOWN,
GPIO_Directions_OUT,
GPIO_Directions_IN,
GPIO_Directions_HARD_PWM,
GPIO_Directions_SIZE
};
c wrapper code:
int setup(int channel, GPIO_Direction direction, int initial)
{
static_assert(GPIO::Directions::SIZE == GPIO_Directions_SIZE,
"c wrapper enum must be equal to c++ enum");
GPIO::setup(channel, static_cast<GPIO::Directions>(direction), initial);
return 0;
}
Assuming you are in control of the C++ headers, too, then you can let the pre-processor generate the enum definitions; you need a set of macros for:
genEnumDefine.h:
// DON'T want include guards!
// otherwise including several headers defining enums that way would fail!
#ifdef __cplusplus
#define ENUM_DEFINITION(NAMESPACE, NAME, CONTENT) \
namespace NAMESPACE \
{ \
enum class NAME \
{ \
CONTENT(NAMESPACE, NAME) \
}; \
}
#define ENUM_ENTRY(N, E, V) V
#else
#define ENUM_DEFINITION(NAMESPACE, NAME, CONTENT) \
enum NAMESPACE##_##NAME \
{ \
CONTENT(NAMESPACE, NAME) \
};
#define ENUM_ENTRY(N, E, V) ENUM_ENTRY_(N, E, V)
#define ENUM_ENTRY_(N, E, V) N##_##E##_##V
#endif
genEnumUndef.h:
#undef ENUM_DEFINITION
#undef ENUM_ENTRY
#ifndef __cplusplus
#undef ENUM_ENTRY_
#endif
Now you can define an enum simply as:
#include <genEnumDefine.h>
#define ENUM_N_E(NAMESPACE, NAME) \
ENUM_ENTRY(NAMESPACE, NAME, E1 = 1), \
ENUM_ENTRY(NAMESPACE, NAME, E2), \
ENUM_ENTRY(NAMESPACE, NAME, E3)
ENUM_DEFINITION(N, E, ENUM_E)
#include <genEnumUndef.h>
You could even define both enums in one single header! You would change the check for __cplusplus for a custom definition and could then do the following:
#define ENUM_N_E(NAMESPACE, NAME) \
ENUM_ENTRY(NAMESPACE, NAME, E1 = 1), \
ENUM_ENTRY(NAMESPACE, NAME, E2), \
ENUM_ENTRY(NAMESPACE, NAME, E3)
#ifdef __cplusplus
#define GEN_ENUM_CPP 1
#include <genEnumDefine.h>
ENUM_DEFINITION(N, E, ENUM_E)
#include <genEnumUndef.h>
#undef GEN_ENUM_CPP
#endif
#include <genEnumDefine.h>
ENUM_DEFINITION(N, E, ENUM_E)
#include <genEnumUndef.h>
Just for illustration...
Life demo (implicit C/C++ check variant).
You cannot use the C++ code in C because it hasn't been written in common subset of the languages.
You can define a corresponding enum in the C wrapper like this for example:
// C
enum Wrapper_Directions
{
Wrapper_Directions_UNKNOWN,
Wrapper_Directions_OUT,
Wrapper_Directions_IN,
Wrapper_Directions_HARD_PWM,
};
int wrapper_setup(int channel, enum Wrapper_Directions direction, int initial);

Calling function before main in static libraries

I have a type registration system for a custom form of runtime type information. Up until now I've used the following macro to call a registration function before main and register the types:
#define REGISTRATION \
static void _register(); \
namespace { struct temp { temp() { _register(); } }; } \
static const temp CAT(temp, __LINE__); \
static void _register()
That way I can do this in lots of different cpp files:
REGISTRATION()
{
RegisterNewType(vec2)
->RegisterMember("x", &vec2::x)
->RegisterMember("y", &vec2::y);
}
This works great. However this falls apart when I try and do this in a static library. It appears that this because C++ does not initialize static variables in static libraries.
I went googling for a solution and found this:
#define REGISTRATION \
static void _register() __attribute__((constructor)); \
static void _register()
Which might solve my problem, but it turns out that I can only do that in clang and gcc. I am using msvc.
Is there a way to get this to work so I can have pre-main functions in libraries?
EDIT: Some more googling brought me to this:
#if defined(_MSC_VER)
#pragma section(".CRT$XCU",read)
#define EXT_REGISTRATION_(f,p) \
static void __cdecl f(void); \
__declspec(allocate(".CRT$XCU")) void (__cdecl*f##_)(void) = f; \
__pragma(comment(linker,"/include:" p #f "_")) \
static void __cdecl f(void)
#ifdef _WIN64
#define EXT_REGISTRATION(f) EXT_REGISTRATION_(f,"")
#else
#define EXT_REGISTRATION(f) EXT_REGISTRATION_(f,"_")
#endif
#else
#define EXT_REGISTRATION(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#endif
However the registration function is still not called. The debugger states that No symbols have been loaded.
As you have a static library, the problem is that by default, only the required symbols will be linked into your executable or library. By definition, these won't be your register static objects.
On Linux, use --whole-archive to tell gcc (or clang) to integrate the full library in the final output file.
On Windows, use /WHOLEARCHIVE.
The other option is to reference these objects from somewhere in your executable/shared library to force their integration.
So two options:
whole archive, easy, but integrates everything from the static library
manually reference the register functions inside say main (just having object; will be enough)
I ended up finding a solution to this in a game engine called Ethereal. Credit goes to that guy for this code.
Instead of having the one register function I have two:
#define CAT_IMPL(a, b) a##b
#define CAT(a, b) CAT_IMPL(a, b)
#define REGISTER_EXTERN(cls)\
template <typename T>\
extern void register_func();\
template <>\
void register_func<cls>();\
static const int CAT(temp, __LINE__) =\
reg_helper::call<cls>(&register_func<cls>)
#define REGISTER(cls)\
template <> \
void register_func<cls>()
And then I have this helper function:
namespace reg_helper
{
template <typename T>
inline int call(void(*f)())
{
static const int s = [&f]() {
f();
return 0;
}();
return s;
}
}
In header functions I define REGISTER_EXTERN(SomeClass);, and then in a cpp filesomewhere I use the register macro like before:
REGISTER(SomeClass)
{
// This code will run before main
}
If you make a header file that lists all your REGISTER_EXTERN calls you can actually specify the order in which the the register functions will be run, since the first time the static is hit, it'll initialize and call the function. The helper ensures that the REGISTER function is only called once, since including the header in different places will re-initialize the static variable in each translation unit.
This solves the problem of static libraries, since the headers will be included and the symbols will exist. And secondly it ensures I can initialize things in the right order.

C++ Macro define and undefine

I want to use macros to quickly create inlined functions in headers, these functions are related to a base class which I am subclassing. I'll put the definitions inside the base class header but I do not want to pollute everything that include these headers with all macro definitions, so I would like to write something like this (which unfortunately doesn't work):
#define BEGIN_MACROS \
#define MACRO_1(...) ...\
#define MACRO_2(...) ...\
#define MACRO_3(...) ...
#define END_MACROS \
#undef MACRO_1\
#undef MACRO_2\
#undef MACRO_3
And then use it like:
BEGIN_MACROS
MACRO_1(...)
MACRO_2(...)
MACRO_3(...)
END_MACROS
perhaps should I use something like this?
#include "definemacros.h"
MACRO_1(...)
MACRO_2(...)
MACRO_3(...)
#include "undefmacros.h"
And put definitions and "undefinitions" in two separate headers...
Or is there a better approach overall to overcome this kind of problems?
Or do you suggest to avoid at all the use of macros and/or macros in headers?
Edited to include specific use case:
definition:
#define GET_SET_FIELD_VALUE_INT(camelcased, underscored)\
inline int rget ## camelcased () { return this->getFieldValue( #underscored ).toInt(); }\
inline void rset ## camelcased (int value) { this->setFieldValue( #underscored , value); }
use:
class PaymentRecord : public RecObj
{
public:
GET_SET_FIELD_VALUE_INT(PriceIndex, price_index)
//produces this
inline int rgetPriceIndex() { return this->getFieldValue("price_index").toInt(); }
inline void rsetPriceIndex(int value) { this->setFieldValue("price_index", value); }
};
you can not stack up more defines into single line (at least to my knowledge... What I would try to do is encapsulate those into 2 separate files instead like this:
file macro_beg.h:
#define MACRO_1(...) ...
#define MACRO_2(...) ...
#define MACRO_3(...) ...
file macro_end.h:
#undef MACRO_1
#undef MACRO_2
#undef MACRO_3
It just like your second case but the macros are not in single line ...
#include "macro_beg.h"
MACRO_1(...);
MACRO_2(...);
MACRO_3(...);
#include "macro_end.h"
But as Some programmer dude commented this might not work properly or at all depending on the compiler preprocessor and macro complexity or nesting with class/template code. For simple stuff however this should work.

Is it possible to use #define inside a function?

For example, I saw source code like the following. Can we use #define in a function? How does it work? (more information: this code is what I copied from openvswitch source code):
void *
ofputil_put_action(enum ofputil_action_code code, struct ofpbuf *buf)
{
switch (code) {
case OFPUTIL_ACTION_INVALID:
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) case OFPUTIL_##ENUM:
#include "ofp-util.def"
OVS_NOT_REACHED();
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
case OFPUTIL_##ENUM: return ofputil_put_##ENUM(buf);
#include "ofp-util.def"
}
OVS_NOT_REACHED();
}
#define OFPAT10_ACTION(ENUM, STRUCT, NAME) \
void \
ofputil_init_##ENUM(struct STRUCT *s) \
{ \
memset(s, 0, sizeof *s); \
s->type = htons(ENUM); \
s->len = htons(sizeof *s); \
} \
\
struct STRUCT * \
ofputil_put_##ENUM(struct ofpbuf *buf) \
{ \
struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s); \
ofputil_init_##ENUM(s); \
return s; \
}
#define OFPAT11_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define OFPAT13_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
OFPAT10_ACTION(ENUM, STRUCT, NAME)
#define NXAST_ACTION(ENUM, STRUCT, EXTENSIBLE, NAME) \
void \
ofputil_init_##ENUM(struct STRUCT *s) \
{ \
memset(s, 0, sizeof *s); \
s->type = htons(OFPAT10_VENDOR); \
s->len = htons(sizeof *s); \
s->vendor = htonl(NX_VENDOR_ID); \
s->subtype = htons(ENUM); \
} \
\
struct STRUCT * \
ofputil_put_##ENUM(struct ofpbuf *buf) \
{ \
struct STRUCT *s = ofpbuf_put_uninit(buf, sizeof *s); \
ofputil_init_##ENUM(s); \
return s; \
}
#include "ofp-util.def"
#define is a preprocessor directive: it is used to generate the eventual C++ code before it is handled to the compiler that will generate an executable. Therefore code like:
for(int i = 0; i < 54; i++) {
#define BUFFER_SIZE 1024
}
is not executed 54 times (at the preprocessor level): the preprocessor simply runs over the for loop (not knowing what a for loop is), sees a define statement, associates 1024 with BUFFER_SIZE and continues. Until it reaches the bottom of the file.
You can write #define everywhere since the preprocessor is not really aware of the program itself.
Sure this is possible. The #define is processed by the preprocessor before the compiler does anything. It is a simple text replacement. The preprocessor doesn't even know if the line of code is inside or outside a function, class or whatever.
By the way, it is generally considered bad style to define preprocessor macros in C++. Most of the things they are used for can be better achieved with templates.
You can use it inside a function, but it is not scoped to the function. So, in your example, the second definitions of a macro will be a redefinition and generate an error. You need to use #undef to clear them first.
You can use #define anywhere you want. It has no knowledge of functions and is not bound by their scope. As the preprocessor scans the file from top-to-bottom it processes #defines as it sees them. Do not be misled (by silly code like this!) into thinking that the #define is somehow processed only when the function is called; it's not.
How does it work? All C/C++ files are first processed by... the preprocessor.
It doesn't know anything about C nor C++ syntax. It simply replaces THIS_THING with ANOTHER THING. That's why you can place a #define in functions as well.
Sure. #define is handled by the preprocessor which occurs well before the compiler has any sense of lines of code being inside functions, inside parameters lists, inside data structures, etc.
Since the preprocessor has no concept of C++ functions, it also means that there is no natural scope to macro definitions. So if you want to reuse a macro name, you have to #undef NAME to avoid warnings.

error C2375: redefinition; different linkage

Error place in api:
#define DLLEXPORT extern "C" __declspec(dllexport)
DLLEXPORT int CAnyseeUSBTVControllerDlg::InitCaptureDevice()
{
In my .h library class and function definition:
class CAnyseeUSBTVControllerDlg : public CDialog
{
// Construction
public:
int InitCaptureDevice(void);
Any idea how to resolve it?
"Error 1 error C2375:
'CAnyseeUSBTVControllerDlg::InitCaptureDevice'
: redefinition; different
linkage c:\Program
Files\toATS_DVS\anysee\anyseee30\anyseee30\anyseeUSBTVControllerDlg.cpp 122 anyseee30"
You have to make sure you use the same declaration in your header file. Otherwise it is seen as different methods.
class CAnyseeUSBTVControllerDlg : public CDialog
{
// Construction
public:
int InitCaptureDevice(void);
DLLEXPORT int CaptureDevice(void);
See Using dllimport and dllexport in C++ Classes
This may happen because
You defined the prototype of a function in different places with
different visibility (extern vs static)
Same as above but
different name mangling (extern "C" vs extern "C++")
Same as above but different dll export (__declspec(dllimport) vs
__declspec(dllexport)).
To solve, enable /p for files to see how they are preprocessed (this has to be in a file by file basis, and will stop generating .obj for that file), look for a .i file with the result.
Or using /displayincludes, or simply greping thru the code.
You can have DLLEXPORT stated in .cpp file, but not in a header file (because otherwise compiler treats these functions as different ones).
Make your definition also DLLEXPORT.
From http://tldp.org/HOWTO/C++-dlopen/thesolution.html
C++ has a special keyword to declare a
function with C bindings: extern "C".
A function declared as extern "C" uses
the function name as symbol name, just
as a C function. For that reason, only
non-member functions can be declared
as extern "C", and they cannot be
overloaded.
I believe static members may also be possible to extern "C", but you can't do what you're trying to do directly. You'll need to make a C-only wrapper interface that calls your class member functions. You can then extern "C" the wrappers and expose that outside your DLL.
//foo.h
#pragma once
#ifdef FOO_EXPORTS
#define FOO_API __declspec(dllexport)
#else
#define FOO_API __declspec(dllimport)
#endif
namespace foo
{
class Baz
{
public:
FOO_API static auto say_hello() -> void;
};
}
The key things, not so much the function names, or my use of the trailing return type, is that you put the name of the #defined __declspec in front of the function you want to export, much like you would a type.
You would also do the same in the function definition:
//foo.cpp
#include "foo.h"
namespace foo
{
FOO_API auto Baz::say_hello() -> void
{
do
{
MessageBox(nullptr, L"Seems to be working okay!", L"OK", MB_OK);
exit(1);
}
while (0);
}
}
The function implementation isn't important, just that you put FOO_API in front.
Today I faced the same issue and for me, I had failed to include the type before my class.
That is I had to change :
class Core
{
private:
py::object cls;
py::object obj;
py::object startFunc;
py::object startFuncAsync;
py::object stopFunc;
...
public:
...
};
to
#ifndef CORE_H
#define CORE_H
/* If we are we on Windows, we want a single define for it.*/
#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__))
#define _WIN32
#endif /* _WIN32 */
#if defined(_WIN32) && defined(_CORE_BUILD_DLL)
/* We are building FV as a Win32 DLL */
#define CORE_API __declspec(dllexport)
#elif defined(_WIN32) && defined(CORE_DLL)
/* We are calling FV as a Win32 DLL */
#define CORE_API __declspec(dllimport)
#elif defined(__GNUC__) && defined(_CORE_BUILD_DLL)
/* We are building FV as a shared / dynamic library */
#define CORE_API __attribute__((visibility("default")))
#else
/* We are building or calling CORE as a static library */
#define CORE_API
#endif
class CORE_API Core
{
private:
py::object cls;
py::object obj;
py::object startFunc;
py::object startFuncAsync;
py::object stopFunc;
...
public:
...
};
Side note:
This will allow for building your project as a dll or a lib and neither of them (i.e. use them by including them) and you can also compile this code under linux, so nothing platform specific here.
If you are in visual studio and want to build a dll, just go to Properties>C/C++>CommandLine and enter :
/D_CORE_BUILD_DLL
and replace CORE with your own designated name.