none
Function template instantation & export from DLL RRS feed

  • Question

  • Hi,

    In my test.cpp I have the following:

    template <class T>
    T Sum(T a, T b)
    {
             return (a + b);
    }

    template __declspec(dllexport) int Sum<int>(int, int);

    So I have defined function template and I used explicit instantiation of Sum<int> function. Compiler and linker produces test.dll from test.cpp without any warnings (and accompanying library files as well).

    In my test.exe I wanna import previously exported instance of a template function:

     

    __declspec(dllimport) int Sum(int, int);


    int main(int argc, char * argv[], char * envp[])
    {
       
       int s = Sum(2,4);
        return 1;
    }

     

    Linker gives me an error   [Linker error] undefined reference to `_imp___Z3Sumii'? How do I import previously exported function template instance in .exe file? (I have included library file in my project).




    • Edited by Franjo555 Saturday, September 10, 2011 8:29 PM
    Saturday, September 10, 2011 8:27 PM

Answers

  • Hi everyone,

    I think I've found a solution. In my previous example with:

     

    template <class T>
    T Sum(T a, T b)
    {
           return (a + b);
    }

    template __declspec(dllexport) int Sum<int>(int, int);

     

     

    compiler & linker produces .dll fine but when I ran dumpbin /exports on that .dll - nothing exported. Code for function instance Sum<int> was generated and put in .text section of that .dll, but apparently not entered in exports table.

    Then I've tried following (in Test.dll):

    template <class T>
    __declspec(dllexport) T Sum(T a, T b)
    {
             return (a + b);
    }


    template int Sum<int>(int, int);

     

    So I've defined function template itself with __declspec(dllexport), and used explicit instantation of Sum<int> function from that function template as stated above. Now, in I've looked in exports table of Test.dll using dumpbin /exports and Sum<int> is there - it got exported.

    Now in .exe program I've done following:

    template <class T>
    __declspec(dllimport) T Sum(T, T);


    int main(int argc, char * argv[], char * envp[])
    {
       
       int s = Sum<int>(2,4);

     

       //float f = Sum<float>(1.2f, 2.56f);
        
        
        return 1;
    }

     
     And it is working! Sum<int> in main is imported from Test.dll, and using OllyDbg it really jumps in Test.dll when called with Sum<int>(2,4).

    Second line: //float f = Sum<float>(1.2f, 2.56f); produces Link error   [Linker error] undefined reference to `_imp___Z3SumIfET_S0_S0_'    as expected, because Sum<float> wasn't instantiated in Test.dll (and if it were instantiated same as Sum<int> it would be automatically exported because whole template is marked with __declspec(dllexport) - every function explicitly instantiated from that function template gets automatically exported from Test.dll).

    In .exe only with template declaration:

    template <class T>
    __declspec(dllimport) T Sum(T, T);

    every function explicitly instantiated in Test.dll gets imported in this .exe and could be used by .exe program.


    P.S. This is tested using Dev-C++ compiler 4.9.9.2. I didn't yet tried Microsoft Visual Studio compiler.
    • Proposed as answer by Do Django Sunday, September 11, 2011 7:17 AM
    • Edited by Franjo555 Sunday, September 11, 2011 8:25 AM
    • Marked as answer by Franjo555 Sunday, September 11, 2011 8:53 AM
    Saturday, September 10, 2011 10:40 PM

All replies

  • Hi Franjo555,

    this will not work, but there are options to solve this issue. Please refer to this thread, this may be the answer you are looking for.

    "The implementation of template functions must be available in accessible header files to enable the compiler to generate the code for the concrete type." ...

    Happy coding...


    "It's time to kick ass and chew bubble gum... and I'm all outta gum." - Duke Nukem

    • Edited by Do Django Saturday, September 10, 2011 9:18 PM
    Saturday, September 10, 2011 9:12 PM
  • Franjo555 wrote:

    In my test.cpp I have the following:

    template <class T>
    T Sum(T a, T b)
    {
    return (a + b);
    }

    template __declspec(dllexport) int Sum<int>(int, int);

    In my test.exe I wanna import previously exported instance of a  template function:

    __declspec(dllimport) int Sum(int, int);

    That's a different function - a non-template one. Try

    template <class T> T Sum(T a, T b);
    template __declspec(dllimport) int Sum<int>(int, int);


    Igor Tandetnik

    Saturday, September 10, 2011 9:19 PM
  • Hi Franjo555,

    I agree with Igor. Memo to myself: Read to the end...


    "It's time to kick ass and chew bubble gum... and I'm all outta gum." - Duke Nukem
    Saturday, September 10, 2011 9:27 PM
  • Hi everyone,

    I think I've found a solution. In my previous example with:

     

    template <class T>
    T Sum(T a, T b)
    {
           return (a + b);
    }

    template __declspec(dllexport) int Sum<int>(int, int);

     

     

    compiler & linker produces .dll fine but when I ran dumpbin /exports on that .dll - nothing exported. Code for function instance Sum<int> was generated and put in .text section of that .dll, but apparently not entered in exports table.

    Then I've tried following (in Test.dll):

    template <class T>
    __declspec(dllexport) T Sum(T a, T b)
    {
             return (a + b);
    }


    template int Sum<int>(int, int);

     

    So I've defined function template itself with __declspec(dllexport), and used explicit instantation of Sum<int> function from that function template as stated above. Now, in I've looked in exports table of Test.dll using dumpbin /exports and Sum<int> is there - it got exported.

    Now in .exe program I've done following:

    template <class T>
    __declspec(dllimport) T Sum(T, T);


    int main(int argc, char * argv[], char * envp[])
    {
       
       int s = Sum<int>(2,4);

     

       //float f = Sum<float>(1.2f, 2.56f);
        
        
        return 1;
    }

     
     And it is working! Sum<int> in main is imported from Test.dll, and using OllyDbg it really jumps in Test.dll when called with Sum<int>(2,4).

    Second line: //float f = Sum<float>(1.2f, 2.56f); produces Link error   [Linker error] undefined reference to `_imp___Z3SumIfET_S0_S0_'    as expected, because Sum<float> wasn't instantiated in Test.dll (and if it were instantiated same as Sum<int> it would be automatically exported because whole template is marked with __declspec(dllexport) - every function explicitly instantiated from that function template gets automatically exported from Test.dll).

    In .exe only with template declaration:

    template <class T>
    __declspec(dllimport) T Sum(T, T);

    every function explicitly instantiated in Test.dll gets imported in this .exe and could be used by .exe program.


    P.S. This is tested using Dev-C++ compiler 4.9.9.2. I didn't yet tried Microsoft Visual Studio compiler.
    • Proposed as answer by Do Django Sunday, September 11, 2011 7:17 AM
    • Edited by Franjo555 Sunday, September 11, 2011 8:25 AM
    • Marked as answer by Franjo555 Sunday, September 11, 2011 8:53 AM
    Saturday, September 10, 2011 10:40 PM
  • Now I've tried same thing with Microsoft Visual Studio 2010 compiler. I my Test.dll I have:

    template <class T>
    T Sum(T a, T b)
    {
         return (a + b);
    }


    template __declspec(dllexport) int Sum<int>(int, int);

     

    And in Main.exe:


    template <class T>
    __declspec(dllimport) T Sum(T,T);


    int main(int argc, char * argv[], char * envp[])
    {

     int s = Sum<int>(1,9);
     
     return 1;

    }

    And this is working with Microsoft C++ compiler. That compiler puts Sum<int> from Test.dll in export table. Apparently Microsoft C++ compiler allow that particular specialization of function template to be instantiated and exported, insted of marking whole template with __declspec(dllexport) and automatically exporting instance from that template.

    • Edited by Franjo555 Sunday, September 11, 2011 8:59 AM
    Sunday, September 11, 2011 8:55 AM
  • I had been looking for the solution for ages and this worked like a charm! I was additionally trying to export the entire template class. For me, I had to additionally forward declare my template parameter classes along with the template specialisations.


    • Edited by mogambo88 Friday, June 1, 2018 12:42 PM
    Friday, June 1, 2018 12:42 PM