Brian Dolan
Brian Dolan

Reputation: 3136

Using Boost Python with CMake on OS X

I am attempting this boost python with cmake example on OS X. The post is a bit old, but I can't find anything newer. My goal is to use CMake (because I'm using CLion) to build an integrated project of C++ and Python libraries. I'm using Python 2.7 on OS X

My .cpp file is

#include <boost/python.hpp>

char const* yay()
{
  return "Yay!";
}

BOOST_PYTHON_MODULE(libyay)
{
  using namespace boost::python;
  def("yay", yay);
}

My CMakesLists.txt

CMAKE_MINIMUM_REQUIRED(VERSION 3.3)
IF(NOT CMAKE_BUILD_TYPE)
  SET(CMAKE_BUILD_TYPE "DEBUG")
  #SET(CMAKE_BUILD_TYPE "RELEASE")
  #SET(CMAKE_BUILD_TYPE "RELWITHDEBINFO")
  #SET(CMAKE_BUILD_TYPE "MINSIZEREL")
ENDIF()

FIND_PACKAGE(PythonLibs 2.7 REQUIRED)

FIND_PACKAGE(Boost)
IF(Boost_FOUND)
  INCLUDE_DIRECTORIES("${Boost_INCLUDE_DIRS}" "/usr/include/python2.7")
  SET(Boost_USE_STATIC_LIBS OFF)
  SET(Boost_USE_MULTITHREADED ON)
  SET(Boost_USE_STATIC_RUNTIME OFF)
  FIND_PACKAGE(Boost COMPONENTS python)

  ADD_LIBRARY(yay SHARED yay.cpp)
  TARGET_LINK_LIBRARIES(yay ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})
ELSEIF(NOT Boost_FOUND)
  MESSAGE(FATAL_ERROR "Unable to find correct Boost version. Did you set BOOST_ROOT?")
ENDIF()


IF(CMAKE_COMPILER_IS_GNUCXX)
  ADD_DEFINITIONS("-Wall")
ELSE()
  SET(CMAKE_CXX_FLAGS "-Wall")
  MESSAGE("You have compiler " ${CMAKE_CXX_COMPILER_ID})
  #MESSAGE(FATAL_ERROR "CMakeLists.txt has not been tested/written for your compiler.")
  MESSAGE("CMakeLists.txt has not been tested/written for your compiler.")
ENDIF()

Finally, I open a Python console and attempt this

from ctypes import *
ly = cdll.LoadLibrary("libyay.dylib")
print ly.yay()

Producing this error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 375, in __getattr__
    func = self.__getitem__(name)
  File "/usr/local/Cellar/python/2.7.12_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py", line 380, in __getitem__
    func = self._FuncPtr((name_or_ordinal, self))
AttributeError: dlsym(0x7fdb5344aec0, yay): symbol not found

I would appreciate guidance on (a) whether this entire approach for integrating C++ and Python is outdated, (b) what this error should tell me and (c) other approaches using CMake.

Upvotes: 2

Views: 1443

Answers (1)

Brian Dolan
Brian Dolan

Reputation: 3136

The key appeared to be that my version of Python was having trouble loading the .dylib files generated by make. I don't know why, so I used this trick in the CMakeLists.txt file and included the if(APPLE) command

cmake_minimum_required( VERSION 3.3 )
project( BoostPythonHelloWorld )

# Make a .so output!
if(APPLE)
set(CMAKE_SHARED_LIBRARY_SUFFIX ".so")
endif(APPLE)

# Find necessary packages
find_package( PythonLibs 2.7 REQUIRED )
include_directories( ${PYTHON_INCLUDE_DIRS} )

find_package( Boost COMPONENTS python REQUIRED )
include_directories( ${Boost_INCLUDE_DIR} )

# Build our library
add_library( greet SHARED greet.cpp )

# Define the wrapper library that wraps our library
add_library( greet_ext SHARED greet_ext.cpp )
target_link_libraries( greet_ext ${Boost_LIBRARIES} ${PYTHON_LIBRARIES} greet )
# don't prepend wrapper library name with lib
set_target_properties( greet_ext PROPERTIES PREFIX "" )

After doing cmake and make I was able to open a Python shell and run

import greet_ext
greet_ext.greet()

I have posted a complete example on github. Also I was to thank Feral Chicken for a a useful post

Upvotes: 2

Related Questions