Coder Social home page Coder Social logo

personalrobotics / chimera Goto Github PK

View Code? Open in Web Editor NEW
13.0 45.0 1.0 995 KB

:snake: A CLI tool for generating Boost.Python/pybind11 bindings from C/C++

License: BSD 3-Clause "New" or "Revised" License

CMake 4.28% C++ 93.26% Shell 0.36% Python 1.48% Dockerfile 0.07% Ruby 0.01% C 0.55%
python cpp boost-python pybind11 clang-toolchain llvm mustache cli chimera

chimera's Introduction

chimera

C/C++ CI Build Status Build Status codecov

chi·me·ra
/kīˈmirə,kəˈmirə/ speaker

informal, noun

  1. a thing that is hoped or wished for but in fact is illusory or impossible to achieve.
  2. a utility to generate Boost.Python bindings for C++ code.

Chimera is a tool for generating Boost.Python/Pybind11 bindings from C/C++ header files. It uses the Clang/LLVM toolchain, making it capable of automatically handling fairly complex source files.

Usage

$ ./chimera -c <yaml_config_file> -o <output_path> my_cpp_header1.h my_cpp_header2.h -- [compiler args]

Installation

On Ubuntu using apt

Chimera provides Ubuntu packages for Xenial (16.04 LTS), Bionic (18.04 LTS), Eoan (19.10), and Focal (20.04).

Xenial and greater

$ sudo add-apt-repository ppa:personalrobotics/ppa
$ sudo apt update
$ sudo apt install chimera

On macOS using Homebrew

# Install the Homebrew package manager
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
# Add Homebrew tap for Personal Robotics Lab software
$ brew tap personalrobotics/tap
# Install Chimera
$ brew install chimera

Build from Source

Requirements

  • libclang 6.0, 7, 8, 9
  • llvm 6.0, 7, 8, 9 (+ tools)
  • libedit
  • yaml-cpp
  • boost

On Ubuntu from Source

Install Dependencies

$ sudo apt-get install llvm-6.0-dev llvm-6.0-tools libclang-6.0-dev libedit-dev \
$   libyaml-cpp-dev libboost-dev lib32z1-dev

Build Chimera

$ git clone https://github.com/personalrobotics/chimera.git
$ cd chimera
$ mkdir build && cd build
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make
$ sudo make install

On macOS from Source

$ brew install boost llvm yaml-cpp
$ brew install eigen  # for examples
$ git clone https://github.com/personalrobotics/chimera.git
$ cd chimera
$ mkdir build && cd build
$ PKG_CONFIG_PATH=$(brew --prefix yaml-cpp)/lib/pkgconfig cmake -DCMAKE_BUILD_TYPE=Release \
    -DLLVM_DIR=$(brew --prefix llvm)/lib/cmake/llvm ..
$ make
$ sudo make install

Example

Let's try running chimera on itself!

$ cd [PATH TO CHIMERA]
$ rm -rf build && mkdir -p build && cd build
$ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
$ make
$ chimera -p . -o chimera_py_binding.cpp ../src/chimera.cpp

Configuration

# The C++ namespaces that will be extracted by Chimera
namespaces:
  - dart::dynamics
  - dart::math

# Selected types that should have special handling.
# (Not implemented yet.)
types:
  'class BodyNode':
    convert_to: 'class BodyNodePtr'

# Selected function and class declarations that need custom parameters.
functions:
  'const Eigen::Vector4d & ::dart::dynamics::Shape::getRGBA() const':
    return_value_policy: copy_const_reference
  'bool ::dart::dynamics::Skeleton::isImpulseApplied() const':
    source: 'test.cpp.in'
  'const Eigen::Vector3d & ::dart::dynamics::Shape::getBoundingBoxDim() const':
    content: '/* Instead of implementing this function, insert this comment! */'
  'Eigen::VectorXd & ::dart::optimizer::GradientDescentSolver::getEqConstraintWeights()': null
    # This declaration will be suppressed.

classes:
  '::dart::dynamics::Shape':
    name: Shape
    bases: []
    noncopyable: true

Troubleshooting

Is there a length limit for the keys in the configuration file of Chimera?

Yes. yaml-cpp does not support more than 1024 characters for a single line key. If you want to use a longer key, then you should use multi-line key.

License

Chimera is released under the 3-clause BSD license. See LICENSE for more information.

Authors

Chimera is developed by Michael Koval (@mkoval) and Pras Velagapudi (@psigen), and it has received major contributions from Jeongseok Lee (@jslee02).

chimera's People

Contributors

jslee02 avatar mkoval avatar psigen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Forkers

tahir1069

chimera's Issues

Generated class declaration is not fully qualified

::boost::python::class_<dart::common::Signal<void (std::shared_ptr<const dart::dynamics::MetaSkeleton>, const std::basic_string<char> &, const std::basic_string<char> &), signal::detail::DefaultCombiner>, ::boost::noncopyable >("Signal", boost::python::no_init)

Note that signal::detail::DefaultCombiner should be dart::common::signal::detail::DefaultCombiner.

Mark classes with no copy assignment operator as noncopyable

/home/mkoval/storage/dart-ws/devel/include/dart/common/Signal.h:240:27: note: copy assignment operator of 'SlotRegister<dart::common::Signal<void (const dart::dynamics::BodyNode *), signal::detail::DefaultCombiner> >' is implicitly deleted because field 'mSignal' is of reference type 'typename Signal<void (const BodyNode *), signal::detail::DefaultCombiner>::SignalType &' (aka 'Signal<void (const dart::dynamics::BodyNode *)> &')
  typename T::SignalType& mSignal;

Attempt to wrap incomplete types

This applies to types that are forward declared in the header file, but the full definition is not available. For example:

/usr/include/boost/python/type_id.hpp:85:9: error: 'typeid' of incomplete type 'Ipopt::IpoptData'
        typeid(T)

in _ZN4dart9optimizer8DartTNLPE.cpp.

Cling does not fully qualify array types

In _ZN4dart3gui6JitterE.cpp we generated:

.add_static_property("j2", []() { return dart::gui::Jitter::j2; }, [](jitter_point [2] value) { dart::gui::Jitter::j2 = value; })

Invalid reference to add_static_property constexpr's

ImportError: ./dartpy.so: undefined symbol: _ZN4dart8dynamics38AddonWithProtectedPropertiesInSkeletonINS0_6detail15ScrewJointAddonENS2_26ScrewJointUniquePropertiesENS0_10ScrewJointEXadL_ZNS2_19JointPropertyUpdateIS3_EEvPT_EELb0EE8OptionalE

This expands to:

dart::dynamics::AddonWithProtectedPropertiesInSkeleton<dart::dynamics::detail::ScrewJointAddon, dart::dynamics::detail::ScrewJointUniqueProperties, dart::dynamics::ScrewJoint, &(void dart::dynamics::detail::JointPropertyUpdate<dart::dynamics::detail::ScrewJointAddon>(dart::dynamics::detail::ScrewJointAddon*)), false>::Optional

Missing typeinfo for some classes

E.g.:

$ python -c 'import dartpy'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: ./dartpy.so: undefined symbol: _ZTIN4dart9optimizer8DartTNLPE

_ZTIN4dart9optimizer8DartTNLPE demangles to typeinfo for dart::optimizer::DartTNLP.

Wrap array member objects as readonly

In _ZN4dart5utils10c3d_head_tE.cpp we get the error:

/usr/include/boost/python/data_members.hpp:64:22: error: array type 'short [244]' is not assignable
          c.*m_which = d;
          ~~~~~~~~~~ ^

Generate setters for const static member variables

E.g.:

/tmp/dartpy/_ZN4dart9optimizer21GradientDescentSolverE.cpp:35:168: error: no viable overloaded '='
.add_static_property("Type", []() { return dart::optimizer::GradientDescentSolver::Type; }, [](const std::string value) { dart::optimizer::GradientDescentSolver::Type = value; })

Unable to set properties on AddonWithProtectedPropertiesInSkeleton

I copied this type out of the Chimera output, but I get this error message if I try to use it in the YAML configuration file:

chimera.util.resolveDeclaration:1:184: error: expected ')'
dart::dynamics::AddonWithProtectedPropertiesInSkeleton<dart::dynamics::detail::EulerJointAddon, dart::dynamics::detail::EulerJointUniqueProperties, dart::dynamics::EulerJoint, &(void dart::dynamics::detail::JointPropertyUpdate<dart::dynamics::detail::EulerJointAddon>(dart::dynamics::detail::EulerJointAddon*)), false>;
                                                                                                                                                                                       ^

I'll break that up a bit:

dart::dynamics::AddonWithProtectedPropertiesInSkeleton<
  dart::dynamics::detail::EulerJointAddon,
  dart::dynamics::detail::EulerJointUniqueProperties,
  dart::dynamics::EulerJoint,
  &(void dart::dynamics::detail::JointPropertyUpdate<   // ERROR
    dart::dynamics::detail::EulerJointAddon>(           // ERROR
      dart::dynamics::detail::EulerJointAddon*)),       // ERROR
  false>;

I don't even think the syntax on those three lines is valid. Any idea what is going on here?

Missing argument names on constructors

The constructors we generate look like this:

.def(::boost::python::init<double, double, double, double, double, bool>()

We should be passing an args() structure to name them, just like we do for methods.

Template functions generate invalid code

typename Derived::PlainObject AdTJacFixed(const Eigen::Isometry3d& _T,
                                          const Eigen::MatrixBase<Derived>& _J)

produces this code:

boost::python::def("AdTJacFixed", static_cast<typename type-parameter-0-0::PlainObject (*)(const Eigen::Transform<double, 3, 1, 0> &, const MatrixBase<type-parameter-0-0> &)>(&dart::math::AdTJacFixed), (::boost::python::arg("_T"), ::boost::python::arg("_J")))

Attempt to generate add_static_property for function pointer type

.add_static_property("UpdateProperties", ::boost::python::make_getter(dart::dynamics::AddonWithProtectedPropertiesInSkeleton<dart::dynamics::detail::PlanarJointAddon, dart::dynamics::detail::PlanarJointUniqueProperties, dart::dynamics::PlanarJoint, &dart::dynamics::detail::JointPropertyUpdate, false>::UpdateProperties))

Attempt to add global variables for constexpr's inside template classes

/home/mkoval/storage/dartpy-ws/src/dartpy/src_generated/_ZN4dart8dynamics46AddonWithProtectedStateAndPropertiesInSkeleton8OptionalE.cpp:11:61: error: 
      'AddonWithProtectedStateAndPropertiesInSkeleton' is not a class, namespace, or enumeration
::boost::python::scope().attr("Optional") = dart::dynamics::AddonWithProtectedStateAndPropertiesInSkeleton::Optional;

Require a user-specified name for template class instantiations

This was generated with no entry in the YAML file:

::boost::python::class_<dart::common::Signal<void (std::shared_ptr<const dart::dynamics::MetaSkeleton>, const std::basic_string<char> &, const std::basic_string<char> &), signal::detail::DefaultCombiner>, ::boost::noncopyable >("Signal", boost::python::no_init)

Note that the class is named Signal, even though there are likely multiple instantiations of this class. This will cause a name conflict in Python.

SEGFAULTs on DART

chimera: /usr/lib/llvm-3.7/include/clang/AST/DeclCXX.h:592: struct DefinitionData &clang::CXXRecordDecl::data() const: Assertion `DD && "queried property of class with no definition"' failed.

Mark classes with noncopyable members as noncopyable

/home/mkoval/storage/dart-ws/devel/include/dart/dynamics/detail/BodyNodePtr.h:52:14: note: copy constructor of 'MutexedWeakSkeletonPtr' is implicitly deleted because field 'mMutex' has a deleted copy constructor
  std::mutex mMutex;
             ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/mutex:128:5: note: 'mutex' has been explicitly marked deleted here
    mutex(const mutex&) = delete;
    ^

std::cout is not fully qualified as a default parameter

In _ZN4dart9optimizer6Solver10PropertiesE.cpp we generate:

/tmp/dartpy/_ZN4dart9optimizer6Solver10PropertiesE.cpp:11:368: error: use of undeclared identifier 'cout'; did you mean 'std::cout'?
  ...= 500, ::boost::python::arg("_iterationsPerPrint") = 0, ::boost::python::arg("_ostream") = &cout, ::boost::python::arg("_printFinalRes...
                                                                                                 ^~~~
                                                                                                 std::cout

Naming

@mkoval and I agree that this repo should be renamed chimera. I mean, look at this badass thing:
image

Constructor arguments are not fully qualified

Chimera just generated this code:

.def(::boost::python::init<const MultiDofJoint<3>::Properties &, const PlanarJoint::UniqueProperties &>())

These constructor arguments should be fully qualified, e.g. dart::dynamics::MultiDofJoint<3>::Properties.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.