Can't use the dictionary for an enum class inside a namespace without the rootmap

Root version: 6.14.04.
I’m creating a dictionary for an enum class defined inside a namespace. From my tests it seems that the .rootmap file is strictly required in order for the interpreter to be aware of the enum class, or in other words it is not sufficient to load the .so dictionary file. I created a small demonstrator:

EnumDictTest.tar.gz (526 Bytes)

where I simply create the dictionary for an enum class. When the .rootmap file is available (for example, when running a root session from the build folder) everything works as expected:

$ root
root [0] .L libMyEnumDict.so
root [1] NS::MyEnum m
(NS::MyEnum) (NS::MyEnum::Alias1) : (int) 0

But if the .rootmap is not available (which is typically my real use case since my libraries resides in various folders not included in LD_LIBRARY_PATH) then I get an error:

$ cd ..
$ root
root [0] .L build/libMyEnumDict.so
root [1] NS::MyEnum m
ROOT_prompt_1:1:1: error: 'NS' is not a class, namespace, or enumeration
NS::MyEnum m
^
ROOT_prompt_1:1:1: note: 'NS' declared here

I don’t know if this is the intended behavior or if I am missing something about the purpose of .rootmap files; in my current understanding it serves just to map a class/enum/whatever to a dictionary library, and thus should not be needed if I load the dictionary library by hand. This error does not occur for an enum class in global scope, so it might be related just to namespaces and not to enum classes.
Thanks in advance for any help.

Hi,

I think you are correct about rootmaps. I am not an expert, but I think the first section in them, marked by the { decls } primitive, is injected in the interpreter upon TROOT initialisation. This allows cling to carry out parsing properly, e.g. knowing about namespaces and fwd declarations of classes and templates. This looks like a requirement to be able to trigger the autoloading/parsing callbacks.

Cheers,
Pnine

Hi Pnine, what you say makes sense to me. What I don’t understand is why I can use a dictionary for a class circumventing the .rootmap by loading the .so manually but I cannot with an enum class.

Hi Nicola,

this is due to the fact that there is no valid autoparse key for that enum in the textual payload injected in the interpreter at library load time. I think you can check the autogenerated dictionary code and TCling::RegisterModule to start debugging if needed.

Cheers

In the dictionary source file I see the enum class mentioned only in TriggerDictionaryInitialization_libMyEnumDict_Impl, in this section:

static const char* classesHeaders[]={
"NS::MyEnum", payloadCode, "@",
nullptr};

That string is then used as argument for TROOT::RegisterModule:

TROOT::RegisterModule("libMyEnumDict",
        headers, includePaths, payloadCode, fwdDeclCode,
        TriggerDictionaryInitialization_libMyEnumDict_Impl, {}, classesHeaders, /*has no C++ module*/false);

I can’t understand whether this should make the enum class visible to the interpreter even when not loading the .rootmap or not.

Hi,

I am not sure since the name “NS::” is not known to the interpreter…
Cheers,
P

In some sense the interpreter should know NS. In the linkdef I put:

#pragma link C++ namespace NS;
#pragma link C++ enum NS::MyEnum;

In fact, when I load the dictionary, type “NS::” and then press tab I get this output:

$ root
root [0] .L libMyEnumDict.so 
root [1] NS::Error in <TClass::LoadClassInfo>: no interpreter information for class NS is available even though it has a TClass initialization routine.
Error in <TClass::LoadClassInfo>: no interpreter information for class NS is available even though it has a TClass initialization routine.

So it seems to me that the interpreter knows about NS, but probably not enough?

@axel I guess this is some cling limitation and you will need to:

root [0] .L libMyEnumDict.so
root [1] #include "MyEnum.h"

Thanks @Wile_E_Coyote, that would certainly solve the problem when using the root command line. But another problem I’m facing is related to saving an array of NS::MyEnum on a Root file. I updated the reproducer:
EnumDictTest.tar (10 KB)
with a small executable saving a class containing a std::array<NS::MyEnum, 2> on file. What I get when executing it is:

$ ./test 
Error in <TStreamerInfo::Build>: MyClass, unknown type: NS::MyEnum e

I don’t know whether this is related to my original post or not (I can open a new thread on this if it’s appropriate, just tell me).

That looks like a bug; I have created https://sft.its.cern.ch/jira/browse/ROOT-10171 - thanks for reporting!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.