Windows10 + Visual Studio 2017 (VC14.1)로 테스트를 했다.
Python 3.7 + tensorflow 2.2 버전이다.
boost는 1.73.0 버전에 python numpy 포함해서 직접 컴파일 하였다.
파이썬에서 C++ 코드를 실행하는 2가지 방법이다.
1. C++에서 Base 클래스를 만들고 이를 파이썬에서 상속받아 클래스를 구현할때 C++에서 코드가 실행되게 하는 방법.
2. C++ 클래스에서 함수들을 만들고 파이썬에서 이를 실행하는 방법.
본인은 Windows10에 아나콘다 가상환경을 설정하지 않았다.
그래서 아나콘다 파이썬 기본 경로가 "C:\\ProgramData\\Anaconda3" 이다.
혹시 아나콘다 가상환경을 구성한 경우 각자 상황에 맞게 아나콘다 경로를 변경한다.
// Copyright Stefan Seefeld 2005.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Boost 기본 예제 boost_1_73_0\libs\python\example\quickstart의 코드.
// 컴파일해서 실행하는 경우 제대로 동작하지 않아 직접수정하여 나중에 쓸려고 올려놓음.
#include <boost/python.hpp>
#include <boost/detail/lightweight_test.hpp>
#include <iostream>
namespace python = boost::python;
// An abstract base class
class Base : public boost::noncopyable
{
public:
virtual ~Base() {};
virtual std::string hello() = 0;
};
// C++ derived class
class CppDerived : public Base
{
public:
virtual ~CppDerived() {}
virtual std::string hello()
{
return "Hello from C++!";
}
};
// Familiar Boost.Python wrapper class for Base
struct BaseWrap : Base, python::wrapper<Base>
{
virtual std::string hello()
{
#if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
// workaround for VC++ 6.x or 7.0, see
// http://boost.org/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions
return python::call<std::string>(this->get_override("hello").ptr());
#else
return this->get_override("hello")();
#endif
}
};
// Boost 기본 예제 boost_1_73_0\libs\python\example\quickstart의 코드
namespace { // Avoid cluttering the global namespace.
// A friendly class.
class hello
{
public:
hello(const std::string& country) { this->country = country; }
std::string greet() const { return "Hello from " + country; }
private:
std::string country;
};
// A function taking a hello object as an argument.
std::string invite(const hello& w) {
return w.greet() + "! Please come soon!";
}
}
// Pack the Base class wrapper into a module
BOOST_PYTHON_MODULE(embedded_hello)
{
python::class_<BaseWrap, boost::noncopyable> base("Base");
}
BOOST_PYTHON_MODULE(extending)
{
using namespace boost::python;
class_<hello>("hello", init<std::string>())
// Add a regular member function.
.def("greet", &hello::greet)
// Add invite() as a member of hello!
.def("invite", invite)
;
// Also add invite() as a regular function to the module.
def("invite", invite);
}
void exec_test1()
{
// Retrieve the main module
python::object main = python::import("__main__");
// Retrieve the main module's namespace
python::object global(main.attr("__dict__"));
// Define the derived class in Python.
python::object result = python::exec(
"from embedded_hello import * \n"
"class PythonDerived(Base): \n"
" def hello(self): \n"
" return 'Hello from Python!' \n",
global, global);
python::object PythonDerived = global["PythonDerived"];
// Creating and using instances of the C++ class is as easy as always.
CppDerived cpp;
BOOST_TEST(cpp.hello() == "Hello from C++!");
std::cout << "testing derived class from C++..." << std::endl;
// But now creating and using instances of the Python class is almost
// as easy!
python::object py_base = PythonDerived();
Base& py = python::extract<Base&>(py_base) BOOST_EXTRACT_WORKAROUND;
// Make sure the right 'hello' method is called.
BOOST_TEST(py.hello() == "Hello from Python!");
std::cout << "success!" << std::endl;
}
void exec_test2()
{
// Retrieve the main module
python::object main = python::import("__main__");
// Retrieve the main module's namespace
python::object global(main.attr("__dict__"));
python::object result = python::exec(
"from extending import * \n"
"hi = hello('California') \n"
"hi.greet() \n",
global, global);
python::object print = python::import("__main__").attr("__builtins__").attr("print");
print(result);
}
void exec_test_error()
{
std::cout << "intentionally causing a python exception..." << std::endl;
// Execute a statement that raises a python exception.
python::dict global;
python::object result = python::exec("print unknown \n", global, global);
python::object print = python::import("__main__").attr("__builtins__").attr("print");
print(result);
}
int main(int argc, char **argv)
{
BOOST_TEST(argc == 2);
std::string script = argv[1];
// Register the module with the interpreter
if (PyImport_AppendInittab("embedded_hello", &PyInit_embedded_hello) == -1)
throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
"builtin modules");
if (PyImport_AppendInittab("extending", &PyInit_extending) == -1)
throw std::runtime_error("Failed to add embedded_hello to the interpreter's "
"builtin modules");
// Initialize the interpreter
Py_SetPythonHome(L"C:\\ProgramData\\Anaconda3");
Py_Initialize();
bool error_expected = false;
if (
python::handle_exception(exec_test1)
|| python::handle_exception(exec_test2)
)
{
if (PyErr_Occurred())
{
if (!error_expected)
BOOST_ERROR("Python Error detected");
PyErr_Print();
}
else
{
BOOST_ERROR("A C++ exception was thrown for which "
"there was no exception translator registered.");
}
}
// Boost.Python doesn't support Py_Finalize yet, so don't call it!
return boost::report_errors();
}
위의 코드를 실행하면 아래와 같은 결과가 나타난다.
'Tensorflow Deep-Learning' 카테고리의 다른 글
[텐서플로] C#에서 tensorflow 사용하기 (4) | 2020.06.10 |
---|---|
[BOOST] 파이썬과 C++의 동거. (numpy array 데이터 공유) (1) | 2020.06.10 |
[BOOST] 빌드 방법 (0) | 2020.06.09 |
[텐서플로] MNIST 관련 4가지 예제 한꺼번에 (tensorflow 1.x) (0) | 2020.06.06 |
[텐서플로] MNIST 관련 코드 실행 오류 발생시 조치 (WIN10) (0) | 2020.06.06 |