Issue
I am currently trying to define a shared library that I aim to use from a Python C++ extension as well as from vanilla C++ applications.
I managed to build the shared library, and tried to link a simple C++ application against it to test its functionalities, but one of the functions of the shared library is treated as an undefined reference by the linker. After checking with nm --demangle --dynamic --defined-only --extern-only libmylib.so
, I realized the function is not being exported by the shared library, but I have no idea why.
The function's signature is as follows:
void bootstrap_mylib(std::vector<std::string> python_path,
std::vector<std::string> python_scripts,
std::string interface_module,
std::function<void (pybind11::module_, pybind11::object)> interface_module_initializer);
Everything goes well if I comment out the last parameter, so the problem seems to be coming from the way I declare the dependencies with pybind11 somehow.
Here are the relevant parts of my CMakeLists.txt:
set(CMAKE_CXX_COMPILER /usr/bin/g++)
project(monilog LANGUAGES CXX VERSION 0.0.1)
set(PYBIND11_PYTHON_VERSION 3.8)
find_package(pybind11 REQUIRED)
include_directories(${PYTHON_INCLUDE_DIRS})
add_library(mylib SHARED MyLib.cc MyLib.h)
set_property(TARGET mylib PROPERTY CXX_STANDARD 17)
target_link_libraries(mylib ${PYTHON_LIBRARIES})
set_target_properties(mylib PROPERTIES VERSION ${PROJECT_VERSION})
set_target_properties(mylib PROPERTIES SOVERSION 1)
set_target_properties(mylib PROPERTIES PUBLIC_HEADER MyLib.h)
Any idea of what I might be doing wrong?
Edit: minimal working example
Here is a minimal example of my problem, consisting of the following files:
example.h
#include <pybind11/stl.h>
namespace Example
{
void simple_func(std::string some_string);
void pybind11_func(pybind11::function some_func);
}
example.cc
#include "example.h"
namespace Example
{
void simple_func(std::string some_string)
{
std::cout << "Simple function" << '\n';
}
void pybind11_func(pybind11::function some_func)
{
std::cout << "Pybind11 function" << '\n';
}
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
cmake_policy(SET CMP0074 NEW)
# SET VARIABLES
set(CMAKE_CXX_COMPILER /usr/bin/g++)
set(CMAKE_CXX_STANDARD 17)
project(example CXX)
set(PYBIND11_PYTHON_VERSION 3.8)
find_package(pybind11 REQUIRED)
# include_directories(${PYTHON_INCLUDE_DIRS})
include_directories(${pybind11_INCLUDE_DIRS})
add_library(example SHARED example.cc example.h)
target_link_libraries(example ${PYTHON_LIBRARIES})
When I build the project, if I then search for func
in the exposed symbols, I get the following result:
> nm -D libexample.so | grep "func"
00000000000039d9 T _ZN7Example11simple_funcENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
pybind11_func
is thus not exported, while simple_func
is correctly exported.
Solution
Namespace pybind11
has hidden visibility.
/usr/include/pybind11/detail/common.h:#
define PYBIND11_NAMESPACE pybind11 __attribute__((visibility("hidden")))
so all functions that have anything to do with that namespace (like having an argument type from it) are also hidden.
You can override this by explicitly setting visibility to default:
__attribute__((visibility("default")))
void bootstrap_mylib( ... )
Answered By - n. 1.8e9-where's-my-share m. Answer Checked By - Willingham (WPSolving Volunteer)