Problem using libtorch to bind C++ modules to Python

username: stepstefan
cooked: <p>Hi,</p>
<p>I needed to bind C++ torch modules to python, but could not find any detailed documentation anywhere.<br>
So I turned to docstring in code, specifically in <code>torch/python.h</code>, and followed minimal example provided in the comments for simple identity module.</p>
<p>Minimal example below</p>
<p>CMakeLists.txt</p>
<pre><code class="lang-auto">cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
project(example VERSION 1.0.0 LANGUAGES C CXX CUDA)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

find_package(Python COMPONENTS Interpreter Development REQUIRED)
find_package(pybind11 CONFIG REQUIRED)
find_package(Torch REQUIRED)

pybind11_add_module(pybind_example tmp.cpp)

target_link_libraries(pybind_example PRIVATE ${TORCH_LIBRARIES})
</code></pre>
<p>tmp.cpp</p>
<pre><code class="lang-auto">#include &lt;torch/extension.h&gt;
#include &lt;pybind11/pybind11.h&gt;

namespace py = pybind11;

struct Net : torch::nn::Module {
    Net(int in, int out) { }
    torch::Tensor forward(torch::Tensor x) { return x; }
};

PYBIND11_MODULE(my_module, m)
{
    torch::python::bind_module&lt;Net&gt;(m, "Net")
        .def(py::init&lt;int, int&gt;())
        .def("forward", &amp;Net::forward);
}
</code></pre>
<p>Code compiles and creates shared library <code>pybind_example.cpython-39-x86_64-linux-gnu.so</code><br>
Problem occurs on import of created module with error</p>
<pre><code class="lang-auto">ImportError: /home/user/tmp/build/pybind_example.cpython-39-x86_64-linux-gnu.so: undefined symbol: THPDtypeType
</code></pre>
<p>Am I missing a linking step? THPDtypeType is defined in <code>torch/csrc/Dtype.h</code>, but I don’t see where it is invoked.</p>
<p>Thank you in advance for any help / ideas.</p>

username: lhycms
cooked: <p>${TORCH_LIBRARIES} doesn’t include header files (such as <code>Python.h</code>) and dynamic link libraries (such as <code>torch_python</code>) required for Python. You must manually add them. If you want to compile it with cmake, you can imitate following CMakeLists.txt template:</p>
<pre><code class="lang-auto">cmake_minimum_required(VERSION 3.14 FATAL_ERROR)
project(example LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED on)


# find pybind11
execute_process(
    COMMAND python3 -c "import pybind11;print(pybind11.__path__[0])"
    OUTPUT_VARIABLE PYBIND11_PATH)
string(REPLACE "\n" "/share/cmake" PYBIND11_CMAKE_PREFIX_PATH ${PYBIND11_PATH})
list(APPEND CMAKE_PREFIX_PATH ${PYBIND11_CMAKE_PREFIX_PATH})
find_package(pybind11 REQUIRED)
# Assign ${PYTHON_INCLUDE_DIRS}
execute_process(
    COMMAND python3-config --exec-prefix 
    OUTPUT_VARIABLE PYTHON_INCLUDE_DIRS)
string(REPLACE "\n" "" PYTHON_INCLUDE_DIRS "${PYTHON_INCLUDE_DIRS}")
string(APPEND PYTHON_INCLUDE_DIRS "/include/python3.9")
message(STATUS ${PYTHON_INCLUDE_DIRS})
# Assign ${TORCH_INCLUDE_DIRS}
execute_process(
    COMMAND python3 -c "from torch.utils import cpp_extension;print(cpp_extension.include_paths())"
    OUTPUT_VARIABLE TORCH_INCLUDE_DIRS)
string(REPLACE "[" "" TORCH_INCLUDE_DIRS "${TORCH_INCLUDE_DIRS}")
string(REPLACE "]" "" TORCH_INCLUDE_DIRS "${TORCH_INCLUDE_DIRS}")
string(REPLACE "'" "" TORCH_INCLUDE_DIRS "${TORCH_INCLUDE_DIRS}")
string(REPLACE "\n" "" TORCH_INCLUDE_DIRS "${TORCH_INCLUDE_DIRS}")
string(REPLACE ", " "\;" TORCH_INCLUDE_DIRS_LIST "${TORCH_INCLUDE_DIRS}")
# Assign ${TORCH_LIBRARY_DIRS}
execute_process(
    COMMAND python3 -c "from torch.utils import cpp_extension;print(cpp_extension.library_paths()[0])"
    OUTPUT_VARIABLE TORCH_LIBRARY_DIRS)
string(REPLACE "\n" "" TORCH_LIBRARY_DIRS "${TORCH_LIBRARY_DIRS}")


pybind11_add_module(pybind_example MODULE ${CMAKE_CURRENT_SOURCE_DIR}/tmp.cpp)
foreach(dir IN LISTS TORCH_INCLUDE_DIRS_LIST)
    target_include_directories(pybind_example PRIVATE ${dir})
endforeach()
target_include_directories(pybind_example PRIVATE ${PYTHON_INCLUDE_DIRS})
target_link_directories(pybind_example PRIVATE ${TORCH_LIBRARY_DIRS})
target_link_libraries(pybind_example PRIVATE c10 torch_cpu torch_python)
</code></pre>
<p>Of course, you can also compile using g++ or torch.utils.cpp_extension module. You must add <code>-lc10</code>, <code>-ltorch</code> and <code>-ltorch_python</code> to ldflags, and add <code>-I&lt;path_to_python&gt;/include/python3.x</code>, <code>-I&lt;path_to_torch&gt;/include/torch/csrc/api/include</code> and <code>-I&lt;path_to_torch&gt;/include</code> to cxxflags.</p>