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>(®ister_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.
Related
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.
I am wrapping a static library in Dll to hide a lot of the implementation stuff since only 4-5 functions are needed and to avoid providing all third-party libraries and many header files. I seem to be having an issue with exporting a function to the dll from the static lib.
The static lib has settings classes / structs similar to the one below
struct FooSettings
{
bool Read(const std::string& file); // implemented in .cpp
bool Write(const std::string& file); // implemented in .cpp
// rest members, just plain types
};
In the Dll side
#include "FooSettings.h"
#if defined(WIN32) || defined(_WIN32)
#if defined(LIB_EXPORT)
// DLL Build, exporting symbols
#define LIB_API __declspec(dllexport)
#elif LIB_IMPORT
// DLL use, importing symbols
#define LIB_API __declspec(dllimport)
#endif
#endif
#ifndef LIB_API
#define LIB_API
#endif
class LIB_API LibSDK
{
public:
LibSDK();
~LibSDK();
FooSettings get() const noexcept;
void set(const FooSettings& settings) const noexcept;
void dummy()
{
foo.Read("");
}
private:
// etc...
};
I can call dummy() on the "client" side without any issues
but the code below leads to unresolved symbols
FooSettings foo;
foo.Read("");
I would have expected that the FooSettings:Read is at least exported since it is part of a dummy function. Am I missing something ? My preference is to export it without the dummy function but I dont seem to be able to make it work either way.
Coming back to all this, the answer was actually to #define LIB_EXPORT in the static library build as well which I did not expect.
I did not think that such a thing would be needed for a static .lib files since all they are is just a bundle of object files so they did not need to be marked for export. Apparently, it was needed if you want to export the functions from the static lib to your wrapper dll.
I'm currently developing a game that comes in two parts: the engine is in a .dll and the actual game code is part of an .exe. The engine, among other header files, contains one that manages all components, ranging from Win32 specific objects and pointers to D3D11. These components are included in a class that allows them to be accessed globally via a function that returns a reference to it. Furthermore, for every item it manages there are two functions that allow the component to be set or to be returned. I also added a thread protection using a critical section.
So, in State.h I have:
#if defined(NF3D_NONCLIENT_BUILD)
#define NF3D_API __declspec(dllexport)
#else
#if defined(__MINGW32__)
#define NF3D_API NF3D_API
#else
#define NF3D_API __declspec(dllimport)
#endif
#endif
...
#endif
...
extern NF3D_API CRITICAL_SECTION CriticalSection;
class NF3D_API NF3DLock
{
public:
#pragma prefast( suppress:26166, "Thread safeness is enabeled." )
FORCEINLINE _Acquires_lock_(CriticalSection) NF3DLock(void) { EnterCriticalSection(&CriticalSection); }
#pragma prefast( suppress:26165, "Thread safeness is enabeled." )
FORCEINLINE _Releases_lock_(CriticalSection) ~NF3DLock(void) { LeaveCriticalSection(&CriticalSection); }
};
class NF3D_API STATE
{
public:
...
inline void SetMember(int val) { NF3DLock Lock; Elements.Member = val; }
inline int GetMember(void) { NF3DLock Lock; return Elements.Member; }
private:
struct ELEMENTS
{
int Member;
} Elements;
}
FORCEINLINE NF3D_API STATE* NF3DGetEngineState(void);
In State.cpp I initialise and delete the critical section but also:
CRITICAL_SECTION CriticalSection;
...
FORCEINLINE NF3D_API STATE* NF3DGetEngineState(void)
{
static STATE s_State;
return &s_State;
}
Calling 'NF3DGetEngineState' inside the .dll causes no problems and the compilation runs perfectly, but if I use this function outside the engine, inside the application I get a linker error in the .exe:
2>Main.obj : error LNK2001: unresolved external symbol "struct _RTL_CRITICAL_SECTION NewFrontiers3D::CriticalSection" (?CriticalSection#NewFrontiers3D##3U_RTL_CRITICAL_SECTION##A)
The engine is included in a namespace called 'NewFrontiers3D'.
This error intrigued me even more when I declared 'extern NF3D_API CRITICAL_SECTION CriticalSection' as static, as it compiled fine but gave an access violation exception when entering the critical section in the constructor of NF3DLock. Also, if I remove 'EnterCriticalSection' and LeaveCriticalSection' the linker errors disappear. I don't know what is happening and why is it happening and that's why I'm addressing this question to anybody who might be able to help me.
Update:
From the line:
#define NF3D_API __declspec(dllexport)
it looks like you are always exporting, and never importing (which you should do when the header is included from external projects).
For example, compile your code using defining NM3D_API_EXPORTS macro (if I am not mistaken: -d option.
And, then, in the header define NM3D_API in the following way:
#ifdef NM3D_API_EXPORTS
#define NM3D_API __declspec(dllexport)
#else
#define NM3D_API __declspec(dllimport)
#endif
Original Post:
Include's work in a very dumb way. They take whole contents of the file you are including, and paste them over the include statement.
This is why, when you are trying to include this header to a different project, that project doesn't know about your declaration in previous .dll. Since it was done in a different file, about which your other project knows nothing about.
I want to have a global names variable, which looks like that
char* names[NAMES_CAP];
int names_len = 0;
And I want every one who links to this library to be able to add an item to this list.
It's easy to do that from main.
int main(int argc,char**argv) {
names[names_len++] = "new name";
names[names_len++] = "new name 2";
}
but what if I want to stack up two libraries? (ie, my library, libnames holds the global variable. And if someone links to libnameuser who uses libnames, it will automatically add all names defined in libnameuser to the names array in libnames.
Is there any way to do that?
In C++, I can insert the names[names_len++] = "..." to the constructor of a global object, and it must be called. But can I do that with plain C?
If you are using gcc you can use the constructor attribute __attribute__((constructor)) to get the same effect. This is however non-standard C.
I would however recommend against this pattern since there is no control of ordering of any function run before main. I would rather find a nice method of hooking in all the "constructor" functions after main has started running.
Update: Refer to https://stackoverflow.com/a/2390626/270788 for updated version of this answer.
Below is a pre-processor abstration to support C static initializer functions with GCC and MSVC. The GCC version will also work with LLVM CC, maybe some other compilers as well.
The MSVC version works by placing a ptr to the static initializer function in a special section that is processed by the application or DLL startup code.
#if defined(__GNUC__)
#define INITIALIZER(f) \
static void f(void) __attribute__((constructor)); \
static void f(void)
#elif defined(_MSC_VER)
#define INITIALIZER(f) \
static void __cdecl f(void); \
__declspec(allocate(".CRT$XCU")) void (__cdecl*f##_)(void) = f; \
static void __cdecl f(void)
#endif
INITIALIZER(initializer_1) { names[names_len++] = "new name"; }
INITIALIZER(initializer_2) { names[names_len++] = "new name 2"; }
If you are not 100% concerned with portability and you can guarantee GCC, you can do what you want with the "constructor" attribute in GCC. See: http://gcc.gnu.org/onlinedocs/gcc-4.1.1/gcc/Function-Attributes.html.
However, I agree with #Anders K when he says you should encapsulate that behaviour in functions.
I think in order to achieve what you want you would be better off to create a couple of wrapper functions to your names[] array. Then modules that access your 'global' names array would have to go through that interface.
This would allow you some better control and decoupling
You could then have the array in one module and then expose a those functions in a header but keep the array hidden.
I think initialization of a global variable works in C too.
int func1();
int someGlobalVariable = func1();
int func1()
{
/* Your initialization code can go here */
}
I hope I'm not mistaking about this working in C (been using only C++ for a very long time now).
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.