CFD Online Discussion Forums

CFD Online Discussion Forums (https://www.cfd-online.com/Forums/)
-   OpenFOAM Programming & Development (https://www.cfd-online.com/Forums/openfoam-programming-development/)
-   -   undefined reference encountered when linking with addToRunTimeSelectionTable (https://www.cfd-online.com/Forums/openfoam-programming-development/92158-undefined-reference-encountered-when-linking-addtoruntimeselectiontable.html)

jsmiles September 4, 2011 07:11

undefined reference encountered when linking with addToRunTimeSelectionTable
 
I am attempting to override/extend the hsCombustionThermo and one of the associated mixture classes (using basicMultiComponentMixture as the base class). These classes are both template classes and the CombustionThermo class has a dual inheritance (using baseHsCombustionThermo and the mixture class -- defined in the template). All appears well until I add the runtime selection to the constructor table. The runtime version of the class needs a hierarchy of templates -- combustion thermo class, mixture class, transport class, species class, thermo properties class, and an equation of state00 class. With that I am using the macros for defineTemplate type and addToRunTimeSelectionTable. Here is the snippet:

namespace Foam
{
typedef mixhsCombustionThermo
<singleComponentMixture <constTransport <specieThermo <hConstThermo<perfectGas>>>>>
mixhsCombustionThermo##singleComponentMixture##con stTransport##hConstThermo##perfectGas;

defineTemplateTypeNameAndDebugWithName
(
mixhsCombustionThermo##singleComponentMixture##con stTransport##hConstThermo##perfectGas,
#mixhsCombustionThermo
"<"#singleComponentMixture"<"#constTransport"<spec ieThermo<"#hConstThermo"<"#hConstThermo">>>>>",
0
);

addToRunTimeSelectionTable
(
baseHsCombustionThermo,
mixhsCombustionThermo##singleComponentMixture##con stTransport##hConstThermo##perfectGas,
theMesh
)
}

This appears to compile fine, but in the final linking of the application the linker complains that it has an undefined reference to the constructor.
-------------------------------------------------------------
undefined reference to 'Foam::mixhsCombustionThermo<Foam::singleComponent Mixture< Foam::constTransport<Foam::specieThermo<Foam::hCon stThermo<FoamerfectGas>>>>>::mixhsCombustionThermo (Foam::fvMesh const&)'
--------------------------------------------------------------
Here are the templates from the base class:

--------------Header----------------------
//- Declare run-time constructor selection tables
declareRunTimeSelectionTable
(
autoPtr,
baseHsCombustionThermo,
theMesh,
(const Foam::fvMesh& mesh),
(mesh)
);

--------------- Impl (C file) -----------------------

namespace Foam
{
defineTypeNameAndDebug(baseHsCombustionThermo, 0);
defineRunTimeSelectionTable(baseHsCombustionThermo , theMesh);
}

and the constructor looks like this:

template<class MixtureType>
Foam::mixhsCombustionThermo<MixtureType>::mixhsCom bustionThermo(const Foam::fvMesh& mesh)
:
hsCombustionThermo(mesh),
MixtureType(*this, mesh)
{
...


---------------------------------------------------------------

If anyone has some experience with this or can see any obvious reasons for the failed reference, your help would be greatly appreciated.

Thanks,

Jeff

l_r_mcglashan September 5, 2011 05:55

Unfortunately templates always 'compile fine', then chuck out horrible errors upon linking!

I have done this myself from scratch before. I assume you've put the constructor method in the .C file and added the .C file to Make/files?

jsmiles September 6, 2011 18:26

Thanks
 
Laurence,

Thanks,

After reading you comments and thinking of how templates classes work I decided to investigate how the template classes are instantiated. As you already know template classes just sit in the code until they are instantiated. Usually this is done at the time they are used as the example

myClassName<parameters> myClassObj();

Unfortunately in the case of the runtime selection table, the invocation is hard to locate. I found another forum post on the stackoverflow.com website that suggested instantiating the class directly in the shared library so that it is present in the shared library prior to the final linking step. This is done via

template class myClassName<parameters>;

So with all the above said, I was finally able to link my final application by adding an explicit instantiation step in the class C file like the following.

template class Foam::mixhsCombustionThermo < Foam::singleComponentMixture < Foam::constTransport < Foam::specieThermo < Foam::hConstThermo < Foam::perfectGas> > > > >;

Do you know if there is another macro in the OpenFoam source code that does the above instantiation? Or have I stepped outside the bounds of what the OpenFoam infrastructure was intended for here?

Thanks,

Jeff

l_r_mcglashan September 7, 2011 03:58

Possibly defineTemplateRunTimeSelectionTable? You can find the macros using the doxygen source code browser on the OF website.

I see you did use that. I'll have to look in more detail.

Back. I used the following in my base class .H:

Code:

#define makeOpSplitType(SS, Type)                                            \
                                                                              \
defineNamedTemplateTypeNameAndDebug(SS<Type>, 0);                            \
                                                                              \
operatorSplit<Type>::addopSplitConstructorToTable<SS<Type> >                  \
    add##SS##Type##ConstructorToTable_;

#define makeOpSplitScheme(SS)                                                \
                                                                              \
makeOpSplitType(SS, scalar)

and in the derived class .C file: makeOpSplitScheme(firstOrderSplit)


All times are GMT -4. The time now is 13:00.