How do I specialize a templated function/class?

Given a simple function, you can create a specialization on the form:

template returnType functionName(arguments);

For example:

#include <string>
#include <vector>

template <typename T>
T getSomething(T something) {
  return something;

template std::string getSomething(std::string);
template std::vector<std::string> getSomething(std::vector<std::string>);

Same for classes:

template <typename T>
class MyClass {
T fun(T type) {
    return type;

template class MyClass<int>;

Then from python they are available as:

import MyLib

# Functions are processed as overloaded, so no name change
print(MyLib.getSomething("Tell tolc I said hi"))
print(MyLib.getSomething(something=["Or", "as", "an", "array"])

# Class specializations have type postfixes
my_class_int = MyLib.MyClass_int()

For more information about type postfixes see the Template Naming Convention page.

I get ImportError: <module>: undefined symbol: _ZN15<class>1<variable>E when I import my module

It might be that there is a static variable not instantiated in a source file. Consider the example:

class Example {
    static int const i = 5;

On its own this will generate an ImportError. To avoid the error, instantiate the static variable inside a .cpp file as:

int const Example::i;

For more information you can read about static member declaration/instantiation on cppreference, or a discussion on this topic in the pybind repository.

At the time of writing there is only experimental support for the Visual Studio generator for Emscripten. If you see error such as:

shell LINK : warning LNK4044: unrecognized option '/-default-obj-ext'; ignored [MyProject.vcxproj] LINK : fatal error LNK1104: cannot open file '.obj' [MyProject.vcxproj] cl : command line warning D9002: ignoring unknown option '-g' [MyProject_wasm.vcxproj] myLib.cppshell

Then consider using the Ninja generator. It is the default on Windows with Visual Studio.