Tuesday, November 7, 2017

Boost python / Cython from ROS catkin build

* 프로젝트에서는 사용했으나, 아래 예제코드로 패키지를 새로 생성해보진 않음.

1. Boost python
1.1  package.xml

<?xml version="1.0"?>
<package format="2">
  <name>some_boost_pkg</name>
  <version>0.0.0</version>

  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>cmake_modules</build_depend>  # 꼭 필요한지 여부 아직 확인 못함
  <export>
  </export>
</package>

1.2  CMakelists.txt

cmake_minimum_required(VERSION 2.8.3)
project(some_boost_pkg)
add_compile_options(-std=c++11) # boost python 컴파일에 c+11이 필요했던걸로 기억함. 아마도.

find_package(catkin REQUIRED COMPONENTS #0
   ~~~~
)

# 아래의 find_package는 윗줄의 #0 이후에 호출할것.
# 버그인지 모르겠으나, ${Boost_LIBRARIES} 등이 공백으로 덮어씌워지는걸 피하기 위해.
# message(${Boost_LIBRARIES}) 로 확인함.
find_package(cmake_modules REQUIRED)
find_package(PythonLibs 2.7 REQUIRED)
find_package(Boost REQUIRED COMPONENTS system filesystem thread python)


include_directories(include
  ${Boost_INCLUDE_DIRS}

   ${PYTHON_INCLUDE_DIRS}
)

 catkin_package(
  LIBRARIES
    my_boost_lib  # 1
)
add_library(my_boost_lib ${~ boost python source codes ~} )
target_link_libraries(my_boost_lib
    ${PYTHON_LIBRARIES}
    ${Boost_LIBRARIES}
)
set_target_properties(my_boost_lib PROPERTIES
    PREFIX ""
    LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION}
) #2

# 1, #2 가 있어야  compile destination이 CATKIN_WORKSPACE/devel/.private/some_boost_pkg/lib/python2.7/dist-packages/some_boost_pkg/my_boost_lib.so 가 된다.
prefix를 안비우면 파일명이 libmy_boost_lib.so 가 된다.

${~ boost python source codes ~}의 소스코드는 부스트 파이선 튜토리얼 참고.
http://www.boost.org/doc/libs/1_62_0/libs/python/doc/html/tutorial/index.html

2. Cython
2. 1 package.xml

boost python과 같음. 패키지 명만 some_boost_pkg 대신 some_cython_pkg 으로 명명했다고 가정하고 진행.

2. 2 CMakeLists.txt

cmake_minimum_required(VERSION 2.8.3)
project(some_cython_pkg)
add_compile_options(-std=c++11)
find_package(catkin REQUIRED)
find_package(cmake_modules REQUIRED)
find_package(PythonLibs 2.7 REQUIRED)

include_directories(includ
  ${catkin_INCLUDE_DIRS}
  ${PYTHON_INCLUDE_DIRS}
)
catkin_package(
  LIBRARIES
      my_cython_lib   # 1
)

catkin_python_setup() # Generate cython_build directory and .c, cxx source codes.
add_library(my_cython_lib
    "cython_build/src/my_cython_codes.c" #3
)
set_target_properties(my_cython_lib PROPERTIES
    PREFIX ""
    LIBRARY_OUTPUT_DIRECTORY ${CATKIN_DEVEL_PREFIX}/${CATKIN_PACKAGE_PYTHON_DESTINATION})  #2

2.3 setup.py

http://wiki.ros.org/rospy_tutorials/Tutorials/Makefile 의 setup.py 파일을 아래와 같이 작성해서 package.xml과 같은 폴더에 저장하면 된다.

#!/usr/bin/python
# -*- coding:utf-8 -*-
## ! DO NOT MANUALLY INVOKE THIS setup.py, USE CATKIN INSTEAD

from distutils.core import setup
from catkin_pkg.python_setup import generate_distutils_setup
from Cython.Build import cythonize

#from catkin_tools.context import Context
#ctx = Context.load()
#build_path = ctx.build_space_abs + "/cython_build" # 경로는 취향에 따라.
build_path = 'cython_build'

setup_args = generate_distutils_setup(
    packages=['some_boost_pkg'], # ROS package name
    package_dir={'': 'src'},
    requires=['std_msgs', 'rospy'], # 만약 코드에서 필요하다면
    ext_modules = cythonize("./src/my_cython_codes.pyx", build_dir=build_path) #3의 경로에 c코드를 생성하게함.
)
setup(**setup_args)

2.4  *.pyx

패키지/src 폴더의 my_cython_codes.pyx 파일은 다음 링크의 hello.pyx 코드 참고해서 작성.

3. Result / Test

위와 같은 방법으로 패키지를 생성하고 catkin build를 수행하면, python에서 다음과 같이 함수 호출 가능.

$ python
>>  import some_boost_pkg.my_boost_lib as m1
>>  import some_cython_pkg.my_cython_lib as m2
>> m1.function1()
>> m2.function2() 




No comments:

Post a Comment