Reputation: 385
For some reason when exposing the below to python using Boost Python, the unique pointer constructor (the obj constructor) fails. This used to work for me before, not sure why it stopped.
#pragma once
#include <memory>
#include <boost/asio/ssl.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast.hpp>
//Socket
class Contextable
{
public:
Contextable() : m_ssl(boost::asio::ssl::context::sslv23_client) {}
protected:
boost::asio::io_context m_ctx;
boost::asio::ssl::context m_ssl;
};
class SocketExample : protected Contextable
{
using SocketImp = boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>;
public:
SocketExample()
{
}
void constructSocket()
{
m_ws = std::make_unique<SocketImp>(m_ctx, m_ssl); //kills jupyter kernel
std::cout << "DONE. OPEN FLAG: " << m_ws->is_open() << std::endl;
}
private:
std::unique_ptr<SocketImp> m_ws;
};
//ExampleModule
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(ExampleModule)
{
boost::python::class_<SocketExample, std::shared_ptr<SocketExample>, boost::noncopyable>("SocketExample")
.def(boost::python::init<>())
.def("constructSocket", &SocketExample::constructSocket)
;
}
##Jupyter Notebook
import ExampleModule as m
socket = m.SocketExample()
socket.constructSocket() ##kills kernel
Any idea what I am doing wrong? When running this using c++ as follows does not fail.
SocketExample sk;
sk.constructSocket(); //works fine when run inside main.cpp
Upvotes: 1
Views: 62
Reputation: 392833
You're most likely pulling in indirect dependencies that are missing from the Jupyter environment.
I've compiled your source (with minor adaptations)
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/beast.hpp>
#include <iostream>
#include <memory>
// Socket
class Contextable {
public:
Contextable() : m_ssl(boost::asio::ssl::context::sslv23_client) {}
protected:
boost::asio::io_context m_ctx;
boost::asio::ssl::context m_ssl;
};
class SocketExample : protected Contextable {
using SocketImp = boost::beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>>;
public:
SocketExample() { std::cout << "SocketExample constructor" << std::endl; }
~SocketExample() { std::cout << "SocketExample destructor" << std::endl; }
void constructSocket() {
m_ws = std::make_unique<SocketImp>(m_ctx, m_ssl);
std::cout << "DONE. OPEN FLAG: " << m_ws->is_open() << std::endl;
}
private:
std::unique_ptr<SocketImp> m_ws;
};
// ExampleModule
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(ExampleModule) {
boost::python::class_<SocketExample, std::shared_ptr<SocketExample>, boost::noncopyable>("SocketExample")
.def(boost::python::init<>())
.def("constructSocket", &SocketExample::constructSocket);
}
A simple CLI test using python:
Starting a Jupyter notebook¹:
As an example of why things would break, let me enable ASAN/UBSAN on the C++ module, by adding
-fsanitize=undefined,address
to the compiler flags. Now, the python CLI test will actually show what's wrong:
We can tell python to load ASAN prior²:
LD_PRELOAD=/nix/store/jfilhsiqdgm4nks2z6labx3iq9qd077a-gcc-13.3.0-lib/lib/libasan.so.8 python ./test.py
And then it works, giving some expectable memory leak reports:
However, if you try to load this into a Jupyter notebook, it won't know how to load the ASAN dependency and fail:
Hopefully this gives you some ideas of what technical issues might be at play, and some ideas of how to start diagnosing them (at least on a Linux-like system as I used).
In general, try to reduce the number of (non-standard) compiler/linker flags. Inspect the shared library (loadable module) for any unexpected/unknown/unavailable dependencies. On Windows, you might use Dependency Walker or - more advanced - Fusion Logging to inspect.
¹ Disclaimer I had never used Jupyter, so I installed it fresh and just winged it...
² I got that path using ldd ExampleModule.so
Upvotes: 1