Search code examples
pythonc++boostcmakeboost-python

Using Boost Python 3.10 and C++ Classes


I'm really confused with initialzing C++ classes when usign boost::python. When compiling the follwing code with CMake I get no error, warning or something else at all:

#include <boost/python.hpp>
#include <iostream>

class Test {

  public:
    Test(int x);
    ~Test();

};

void greet() {
  Test test(10);
  std::cout << "Test" << std::endl;
}

BOOST_PYTHON_MODULE(libTestName)
{
  Py_Initialize();

  using namespace boost::python;

  def("greet", greet);
}

With the follwoing CMakeLists.txt:

cmake_minimum_required (VERSION 3.8)
project (libTestLib)

IF(NOT CMAKE_BUILD_TYPE)
  SET(CMAKE_BUILD_TYPE "RELEASE")
ENDIF()


# Add all the files to the library so it can get created
ADD_LIBRARY(TestLib SHARED
                    main.cpp)


# Set the Flags and the CXX command
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} -Wall -Wextra -fconcepts")


set(boostPython python3)
find_package(PythonInterp 3.6 REQUIRED)
find_package(PythonLibs 3.6 REQUIRED)

include_directories(${PYTHON_INCLUDE_DIRS})

set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)  
set(Boost_USE_STATIC_RUNTIME OFF)
FIND_PACKAGE(Boost REQUIRED COMPONENTS system program_options numpy ${boostPython})


if(Boost_FOUND)

    include_directories(${Boost_INCLUDE_DIRS})
    target_link_libraries(TestLib ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})

else()

    message(FATAL_ERROR "Could not find boost.")

endif()

I get the follwoing error code when I try to import this lib into Python:

>>> import build.libPathFinding
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: path/to/lib/libTestLib.so: undefined symbol: _ZN4TestD1Ev

I fuígured out that it is possible to create a pointer to a new object with the follwoing code:

void greet() {
  Test *test = new Test(10);
  std::cout << "Test" << std::endl;
}

But then I'm unable to free this pointer again by using delete because I'll get again an import error from Python.


Solution

  • Just use a constructor and destructor like:

    #include <boost/python.hpp>
    #include <iostream>
    
    class Test {
    
      public:
        Test(int x) {};  // Change
        ~Test() {};  // Change
    
    };
    
    void greet() {
      Test test(10);
      std::cout << "Test" << std::endl;
    }
    
    BOOST_PYTHON_MODULE(libTestName)
    {
      Py_Initialize();
    
      using namespace boost::python;
    
      def("greet", greet);
    }