Exporting templat instantiations from DLLs.

OPEN

Given the following example :

CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)
project(export_templates CXX)
include(GenerateExportHeader)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)

add_library(mylib SHARED header.hpp mylib.cpp)
generate_export_header(mylib)

add_executable(myexe header.hpp main.cpp)
target_link_libraries(myexe mylib)

header.hpp:

#pragma once
#include <vector>
template<typename T>
struct foo
{
    std::size_t bar() {
        std::vector<T> t;
        t.resize(10);
        return t.size();
    }
};

extern template struct foo<int>;

mylib.cpp:

#include "header.hpp"

#include <mylib_export.h>
template struct MYLIB_EXPORT foo<int>;

main.cpp:

#include "header.hpp"

int main()
{
    foo<int> f;
    return f.bar();
}

I get the following linker error:

[ 75%] Linking CXX executable myexe
CMakeFiles/myexe.dir/main.cpp.o: In function `main':
main.cpp:(.text+0x1f): undefined reference to `foo<int>::bar()'

What can I do to get this to link, with the following requirements:

  • Should work on linux (.so), macOS (.dylib), windows (.dll)
  • With latest gcc, msvc, and clang.
  • Without adding MYLIB_EXPORT to the definition of struct foo (since in the real case, struct foo is not under my control).
  • Without suggesting the use of static linking - If I could, I would.

Thanks !

Posted Mar 13, 2018, 6:07 PM UTC

43
ptitz•

I might be wrong, but AFAIK the template types get resolved at compile time, so they can't be used with dynamic linking. Your options are making a header-only lib, using a static link or ditching the template.

1
doom_Oo7OP•

but AFAIK the template types get resolved at compile time

no, templates can be resolved at link time: https://godbolt.org/g/PW9acw

in particular, the syntax template struct foo<int>; does explicit instantiation of the template so that all defined functions be generated: https://godbolt.org/g/ecRwCM

1
ptitz•

Yeah, but here the thing is done at compile time. Like with static linking. When you use a dynamic lib linking is done at load time. And you can't resolve templates then.

1