Я пытался скомпилировать это example.cpp
из учебника по pybind11 под названием pybind11_examples
на GitHub.
#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <Eigen/LU>
#include <iostream>
// ----------------
// regular C++ code
// ----------------
Eigen::MatrixXd mul(const Eigen::MatrixXd &xs, double fac)
{
std::cout << "Double" << std::endl;
return fac*xs;
}
Eigen::MatrixXi mul(const Eigen::MatrixXi &xs, int fac)
{
std::cout << "Int" << std::endl;
return fac*xs;
}
// ----------------
// Python interface
// ----------------
namespace py = pybind11;
PYBIND11_MODULE(example,m)
{
m.doc() = "pybind11 example plugin";
// N.B. the order here is crucial, in the reversed order every "int" is converted to a "double"
m.def("mul", py::overload_cast<const Eigen::MatrixXi &,int >(&mul) );
m.def("mul", py::overload_cast<const Eigen::MatrixXd &,double>(&mul) );
}
и соответствующий CMakeLists.txt
файл
cmake_minimum_required(VERSION 2.8.12)
project(example)
set (CMAKE_CXX_STANDARD 14)
find_package( PkgConfig )
pkg_check_modules( EIGEN3 REQUIRED eigen3 )
include_directories( ${EIGEN3_INCLUDE_DIRS} )
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
У меня есть одно замешательство: почему нам не нужно связывать Eigen
с example
. Это потому, что Eigen
— это библиотека только для заголовков, поэтому include_directories
достаточно? Тогда что мне делать с библиотеками, не предназначенными только для заголовков?
Заранее спасибо!
Обновлено: Чтобы ответить на ваш вопрос о том, что делать с библиотеками не только для заголовков:
Pybind11 pybind11_add_module
работает так же, как CMakes add_executable
или add_library
, он определяет цель (первый аргумент), с которой вы затем можете связать. В твоем случае:
#Rest of the CMakeLists.txt...
pybind11_add_module(example example.cpp)
target_link_libraries(example my_library)
#Rest of the CMakeLists.txt...
Как уже писал пользователь @user253751 в комментариях. Eigen — это библиотека только для заголовков. Вы можете убедиться сами на их домашней странице:
Требования
Eigen не имеет никаких зависимостей, кроме стандартной библиотеки C++.
Мы используем систему сборки CMake, но только для сборки документации и юнит-тестов, а также для автоматизации установки. Если вы просто хотите использовать Eigen, вы можете сразу использовать заголовочные файлы. Нет бинарной библиотеки для ссылки и настроенного файла заголовка. Eigen — это чистая библиотека шаблонов, определенная в заголовках.
Любая идея, что я должен сделать для библиотек, отличных от заголовков?
@QualsPassed хорошо, вы сами ответили на вопрос, то есть: используйте target_link_libraries
и свяжите его со своим исполняемым файлом / библиотекой. pybind11_add_module
Pybind11 работает так же, как add_executable
или add_library
, он определяет цель (первый аргумент), с которой вы затем можете связать.
Итак, добавьте строку ниже pybind11_add_module
, например, target_link_libraries(example <library>)
? Означает ли это, что если я сделаю find_package(Eigen3 3.3)
и target_link_libraries(example Eigen3::Eigen)
, он также сможет строить? Я попробовал это, и это не работает.
@QualsPassed Вам не нужно делать это с Eigen, поскольку Eigen - это только заголовок. Но если вы, например, хотите связать OpenCV
, вам придется сделать target_link_libraries
. С eigen все, что вам нужно сделать, это сделать заголовки доступными, что вы делаете, вызывая эту команду include_directories( ${EIGEN3_INCLUDE_DIRS} )
Да, я понимаю это с Eigen
Мне не нужно этого делать, я просто использовал Эйгена в качестве примера.
@QualsPassed ах, я неправильно понял, мой плохой.
Подробнее о проблеме target_link_library
я попробовал следующее CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(example)
set (CMAKE_CXX_STANDARD 14)
find_package(Eigen3 3.3)
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
target_link_libraries(example Eigen3::Eigen)
И мне выдаст ошибку:
CMake Error at CMakeLists.txt:14 (target_link_libraries):
The keyword signature for target_link_libraries has already been used with
the target "example". All uses of target_link_libraries with a target must
be either all-keyword or all-plain.
The uses of the keyword signature are here:
* pybind11/tools/pybind11Tools.cmake:179 (target_link_libraries)
* pybind11/tools/pybind11Tools.cmake:211 (target_link_libraries)
Это потому, что две строки, упомянутые выше, вызывают target_link_libraries
как
179: target_link_libraries(${target_name} PRIVATE pybind11::module)
211: target_link_libraries(${target_name} PRIVATE pybind11::lto)
Это вызывает ошибку, потому что, как указано в сообщении об ошибке:
все использования
target_link_libraries
с целью должны быть либоall-keyword
, либоall-plain
.
all-keyword
относится к включению PRIVATE|PUBLIC|INTERFACE
в вызов target_link_libraries
, как в двух строках выше.
all-plain
означает не включать PRIVATE|PUBLIC|INTERFACE
в команду target_link_libraries
, например:
target_link_libraries(example Eigen3::Eigen)
Мы должны выбрать один из вышеперечисленных способов использования команды target_link_libraries
в одном файле CMakeLists.txt
. Поскольку pybind11
сделал этот выбор за нас, используя вызов по ключевому слову, мы также должны сделать то же самое. Итак, если мы используем
target_link_libraries(example PRIVATE Eigen3::Eigen)
он будет успешно скомпилирован. Если мы используем PUBLIC
вместо PRIVATE
, он также успешно скомпилируется.
IIRC Eigen — это библиотека только для заголовков, что означает, что весь код находится в файлах .h, и ваш проект его компилирует.