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:
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:
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.
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.
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.
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.
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?
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).