Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forcing Compile-Time Type Registration #208

Open
jkunstwald opened this issue Nov 30, 2018 · 9 comments
Open

Forcing Compile-Time Type Registration #208

jkunstwald opened this issue Nov 30, 2018 · 9 comments

Comments

@jkunstwald
Copy link

I want to use RTTR to get a unique ID for a type (class), serialize it, deserialize it, and then instantiate that class (on a different machine, over the network).

Since type::get_id() is not unique across process executions, my idea is to use type::get_name(). A string is too long, so i want to hash the strings and cache them. This cache should be complete right after the process launches, its content is known at compile time. Im using a singleton which iterates over type::get_derived_classes() in its constructor (of a specific class type of interest).

However, the derived class types are not available immediately, some sort of interaction with each derived type has to have come first. Is there a clean way of forcing the RTTR registration to fully register a type?

In the simplest example, you have Foo.h:

#pragma once
#include <rttr/type>

class Foo { RTTR_ENABLE() };
class DerivedFoo: public Foo { RTTR_ENABLE(Foo) };

and Foo.cpp:

#include "Foo.h"
#include <rttr/registration>

RTTR_REGISTRATION
{
    rttr::registration::class_<Foo>("Foo").constructor<>();
    rttr::registration::class_<DerivedFoo>("DerivedFoo").constructor<>();
}

Now, if nothing has happened with either Foo or DerivedFoo (an instantiation or a call to type::get<DerivedFoo>) before constructing the singleton, it will not find DerivedFoo. And even then, if the singleton is included before Foo.h, it will also not find DerivedFoo. Is there an elegant solution to this issue, or am i missing something else entirely which makes this unnecessary?

@acki-m
Copy link
Contributor

acki-m commented Dec 1, 2018

The type is available to RTTR, when this code here:

RTTR_REGISTRATION
{
    rttr::registration::class_<Foo>("Foo").constructor<>();
    rttr::registration::class_<DerivedFoo>("DerivedFoo").constructor<>();
}

gets executed. And this code here will be automatically executed, before main is called.
Does this answer your question?

@jkunstwald
Copy link
Author

Huh, i have found my issue: My .cpp files with the RTTR_REGISTRATION blocks are part of a library which gets declared as

add_library(my-library STATIC ${SOURCE_FILES} ${HEADER_FILES})

and then linked to in the executable

target_link_libraries(my-executable PRIVATE my-library)

And it in this case it looks like, the RTTR_REGISTRATION blocks are not (unconditionally) executed before the my-executable main is called.

Did you ever encounter this issue? Can something be done about this? If i add a dummy executable to the library itself with all of the .cpp files as CMake sources, the blocks execute just fine before its main is called.

@acki-m
Copy link
Contributor

acki-m commented Dec 4, 2018

You mean that the RTTR_REGISTRATION part get optimized out?

@jkunstwald
Copy link
Author

Yes, i think so.

@CosmicRey
Copy link
Contributor

CosmicRey commented Mar 9, 2019

Hey, I have also been having issues with RTTR_REGISTRATION not being invoked before main() when linked from a static library, I am currently testing in debug in MSVC in C+17. Any ideas why this could be happening?

Update: I was able to fix my problem... Ensure that the linker options "Use Library Dependency Inputs" and "Link Library Dependencies" are enabled

@TheAifam5
Copy link

In Visual Studio you can use "Use library Dependency Inputs" in the "Linker > General" to fix that problem. In GCC just link with .o objects.

You can try with __attribute__ ((used)).

@emxaz
Copy link

emxaz commented Sep 24, 2019

Does anyone have a general solution to this that doesn't rely on specific linker flags? I seem to be running into the same problem: the registration logic for things defined in a static library is not being invoked unconditionally in a consuming application. If I add a dummy function to the same translation unit and invoke that from my consuming application, then the registration logic DOES run.

@DavidColson
Copy link

@emxaz the method of registering as shown in this issue solves this, though it's a more verbose way of registering types: #106

@MickAlmighty
Copy link

I had the same problem with MSVC, but in my case when I use CMake I could't set "Use library Dependency Inputs" flag in the Visual Studio project's linker properties.
For MSVC CMake project the solution was to link the static library to the executable in such way:
target_link_libraries(exec static_lib -WHOLEARCHIVE:$<TARGET_FILE:static_lib>)

MSDN reference: https://docs.microsoft.com/en-us/cpp/build/reference/wholearchive-include-all-library-object-files?view=msvc-170

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants