Это мой первый вопрос, поэтому прошу прощения за длинный пост. (Я также новичок в C ++)
Я пытаюсь импортировать Quantlib в python с помощью pybind11. Модуль успешно собран, и его можно успешно импортировать в python3. Однако я получаю segmentation fault 11, когда пытаюсь запустить его. Я решил, что проблема возникает, когда я пытаюсь создать указатель на «DiscountingBondEngine». Ниже упрощенный фрагмент кода:
#include <ql/pricingengines/bond/discountingbondengine.hpp>
#include <iostream>
#include <iomanip>
using namespace QuantLib;
int bond(int tmp) {
DiscountingBondEngine *p = new DiscountingBondEngine;
delete p;
return 0;
}
/***************
Pybind extension
****************/
#include <pybind11/pybind11.h>
namespace py = pybind11;
PYBIND11_MODULE(qlBond, m) {
m.def("bond", &bond, R"pbdoc(
ql bonds.
)pbdoc");
#ifdef VERSION_INFO
m.attr("__version__") = VERSION_INFO;
#else
m.attr("__version__") = "dev";
#endif
}
Я использую Ma c OSX: 10.13.6, Python 3.7. Я пробовал как дистрибутив Anaconda, так и дистрибутив brew python. Ниже файла setup.py
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext
import sys
import setuptools
import os
__version__ = '0.0.1'
libraries = ['QuantLib']
library_dirs = ['/usr/local/lib']
class get_pybind_include(object):
"""Helper class to determine the pybind11 include path
The purpose of this class is to postpone importing pybind11
until it is actually installed, so that the ``get_include()``
method can be invoked. """
def __str__(self):
import pybind11
return pybind11.get_include()
ext_modules = [
Extension(
'qlBond',
# Sort input source files to ensure bit-for-bit reproducible builds
# (https://github.com/pybind/python_example/pull/53)
sorted(['BondsP.cpp']),
library_dirs=library_dirs,
libraries=libraries,
include_dirs=[
# Path to pybind11 headers
get_pybind_include(),
'usr/local/include',
'usr/local/include/boost',
],
language='c++'
),
]
# cf http://bugs.python.org/issue26689
def has_flag(compiler, flagname):
"""Return a boolean indicating whether a flag name is supported on
the specified compiler.
"""
import tempfile
import os
with tempfile.NamedTemporaryFile('w', suffix='.cpp', delete=False) as f:
f.write('int main (int argc, char **argv) { return 0; }')
fname = f.name
try:
compiler.compile([fname], extra_postargs=[flagname])
except setuptools.distutils.errors.CompileError:
return False
finally:
try:
os.remove(fname)
except OSError:
pass
return True
def cpp_flag(compiler):
"""Return the -std=c++[11/14/17] compiler flag.
The newer version is prefered over c++11 (when it is available).
"""
flags = ['-std=c++17', '-std=c++14', '-std=c++11']
for flag in flags:
if has_flag(compiler, flag):
return flag
raise RuntimeError('Unsupported compiler -- at least C++11 support '
'is needed!')
class BuildExt(build_ext):
"""A custom build extension for adding compiler-specific options."""
c_opts = {
'msvc': ['/EHsc'],
'unix': [],
}
l_opts = {
'msvc': [],
'unix': [],
}
if sys.platform == 'darwin':
darwin_opts = ['-stdlib=libc++', '-mmacosx-version-min=10.9']
c_opts['unix'] += darwin_opts
l_opts['unix'] += darwin_opts
def build_extensions(self):
ct = self.compiler.compiler_type
opts = self.c_opts.get(ct, [])
link_opts = self.l_opts.get(ct, [])
if ct == 'unix':
opts.append(cpp_flag(self.compiler))
if has_flag(self.compiler, '-fvisibility=hidden'):
opts.append('-fvisibility=hidden')
for ext in self.extensions:
ext.define_macros = [('VERSION_INFO', '"{}"'.format(self.distribution.get_version()))]
ext.extra_compile_args = opts
ext.extra_link_args = link_opts
build_ext.build_extensions(self)
setup(
name='qlBond',
version=__version__,
author='dp',
author_email='',
url='',
description='',
long_description='',
ext_modules=ext_modules,
setup_requires=['pybind11>=2.5.0'],
cmdclass={'build_ext': BuildExt},
zip_safe=False,
)
Я использую
pip install (Success);
import qlBond (Sucess);
qlBond.bond(2) (failed!)
Segmentation fault: 11
Под файлом заголовка Discountbondengine.hpp
#ifndef quantlib_discounting_bond_engine_hpp
#define quantlib_discounting_bond_engine_hpp
#include <ql/instruments/bond.hpp>
#include <ql/termstructures/yieldtermstructure.hpp>
#include <ql/handle.hpp>
namespace QuantLib {
class DiscountingBondEngine : public Bond::engine {
public:
DiscountingBondEngine(
const Handle<YieldTermStructure>& discountCurve =
Handle<YieldTermStructure>(),
boost::optional<bool> includeSettlementDateFlows = boost::none);
void calculate() const;
Handle<YieldTermStructure> discountCurve() const {
return discountCurve_;
}
private:
Handle<YieldTermStructure> discountCurve_;
boost::optional<bool> includeSettlementDateFlows_;
};
}
#endif