Linker __declspec problem [solved]

Hello,

Working on a PV derived custom application I am writing some “editor” module (in the form of a non-modal dialog) that can be opened through the main application action menus and toolbars. So I also wrote a “…Reaction” class, like there are others defined in ParaView. And also like for others, I declared it as follows in the *.h file:

class PQAPPLICATIONCOMPONENTS_EXPORT atgConstraintsEditorReaction: public pqReaction
{
Q_OBJECT
typedef pqReaction Superclass;

This works all fine on Linux, but on a Windows system I am getting the following message:

atgConstraintsEditorReaction::staticMetaObject : definition of dllimport static data member not allowed

Yes, right, this is what happens: that PQ…_EXPORT macro generates some _declspec(dllimport), and the Q_OBJECT triggers the preparation of some moc…cpp file that contains some static data members.

But now my problem is still: Looking for differences between my “Reaction” class and others in Paraview, I do not find anything!

Only the fact that “the others” are compiling and linking, but mine gives that error message…

If I simply drop that macro the error goes away of course, but then others come in, like the one or other function or data items are not found by the linker - which obviously do exist. So this cannot be the correct way either.

With the help of Google I find others who had similar problems in the past, but so far no solution that I could a) understand and b) apply to my own case, so I am still lost.

Any hint or help is very much appreciated!

Regards,
Cornelis

PQAPPLICATIONCOMPONENTS_EXPORT is indeed incorrect for any class outside of ParaView/Qt/ApplicationComponents. You should indeed drop it.

Now the question becomes do you need any export macros at all. Are you creating multiple libraries and using this class a library different from the one its added in? Then you’d need to to generate an appropriate export header for your library and then add the correct export macro for your library. See CMake docs for the GENERATE_EXPORT_HEADER, that should get you started.

Thanks a lot for that hint - or rather two: Dropping PQAPPLICATIONCOMPONENTS_EXPORT saves me already a lot of research about how to do it better.

Regarding the second question I will have to analyze a bit further. Because this is actually how I proceeded:

  1. I had that error message with the “dllimport”… - and dropped the macro

  2. I got some linker error about an “unresolved external symbol” that I found was actually present in both dll and lib (in correctly mangled form and all), but only found in the Linux version of the software. However, analyzing the Windows variant I had also already found out that there was some strange order of the lib files in the link command:


a.lib

b.lib

where the function required in a.lib was only found in b.lib - which is in my understanding normal Windows linker behaviour.

However, I had listed both a and b as “EXTERNAL_DEPENDENCIES” in the BUILD_PARAVIEW_CLIENT(…) macro call - and I had added them in the correct order: first b, then a later on.

But somehow they ended up in the wrong order in the “link.exe…” command.

So “somebody” (some automatism) changes the order to the worse…

Which then brought me back to asking myself whether I should still use that PQAPPLICATIONCOMPONENTS_EXPORT macro in the first place - which only brought me back to where I was before…

So basically I know now that I will have to rather investigate the other track and find out why the order in the link command ends up the wrong way round.

Regards,
Cornelis

If you have two libraries A and B and A requires something from B, you have add target_link_libraries(A PRIVATE|PUBLIC B) independent of what you tell BUILD_PARAVIEW_CLIENT() macro.

Right - thanks again!

This was actually the next thing I tried, running into another problem that I finally solved: The TARGET_LINK_LIBRARIES(…) collided with some QT5 stuff, and I first had to find out that using QT5_USE_MODULES was causing it and I had to replace that one with

FIND_PACKAGE(Qt5 REQUIRED Widgets Xml)

TARGET_LINK_LIBRARIES(A PRIVATE Qt5::Widgets Qt5::Xml A)

This at least went through CMake again, but still the problem with the correct link order is not solved yet. Ok, there are more such cases in my project which is already quite large, so I may have to go through it and check if I have no circular dependencies that may fool the CMake reordering of modules.

Problem finally solved! And it was finally none of the tracks I followed for hours, but simply some Microsoftish quirk.

Basically the problem is described - and solved - here: https://stackoverflow.com/questions/2479784/exporting-static-data-in-a-dll

I had in my class a public declaration like this:

static std::vector<Operand> allComp_;

and from some other module I was directly addressing allComp_. Maybe not the best style, but you would expect it to work - and it actually does in Linux. The most confusing thing is that the symbol even appears in the symbols of the dll and lib, with mangling exactly matching, which mislead me to looking in completely wrong directions, like with the __declspec and the link order.

My solution is now to drop that static data export altogether and go for something better. Otherwise a workaround would be - as recommended in the link above: have the static data member private and only access it through a function that should not be inlined.

And thanks to Utkarsh for cutting one of the detours that I was trying!