Fully-transparent exposure of Eigen::Vector/Matrix types using pybind11 - pybind11

I have a simple class definition:
class State {
private:
Eigen::Vector3f m_data;
public:
State(const Eigen::Vector3f& state) : m_data(state) { }
Eigen::Vector3f get() const { return m_data; }
void set(const Eigen::Vector3f& _state) { m_data = _state; }
std::string repr() const {
return "state data: [x=" + std::to_string(m_data[0]) + ", y=" + std::to_string(m_data[1]) + ", theta=" + std::to_string(m_data[2]) + "]";
}
};
I then expose the above in python with pybind11:
namespace py = pybind11;
PYBIND11_MODULE(bound_state, m) {
m.doc() = "python bindings for State";
py::class_<State>(m, "State")
.def(py::init<Eigen::Vector3f>())
.def("get", &_State::get)
.def("set", &_State::set)
.def("__repr__", &_State::repr);
}
And everything works fine; I am able to import this module into python and construct a State instance with a numpy array. This isn't exactly what I want though. I want to be able to access this object as if it were a numpy array; I want to be able to do something like the following in python:
import bound_state as bs
arr = np.array([1, 2, 3])
a = bs.State(arr)
print(a[0])
(the above throws a TypeError: 'bound_state.State' object does not support indexing)
In the past, I've used boost::python to expose lists by using add_property and this allowed indexing of the underlying data in C++. does pybind11 have something similar that can work with Eigen? Could someone provide an example showing how to expose a State instance that is indexable?

Per the API Docs, this can be done easily with the def_property method.
Turn this bit:
namespace py = pybind11;
PYBIND11_MODULE(bound_state, m) {
m.doc() = "python bindings for State";
py::class_<State>(m, "State")
.def(py::init<Eigen::Vector3f>())
.def("get", &State::get)
.def("set", &State::set)
.def("__repr__", &State::repr);
}
Into this:
namespace py = pybind11;
PYBIND11_MODULE(bound_state, m) {
m.doc() = "python bindings for State";
py::class_<State>(m, "State")
.def(py::init<Eigen::Vector3f>())
.def_property("m_data", &State::get, &State::set)
.def("__repr__", &State::repr);
}
Now, from the python-side, I can do:
import bound_state as bs
arr = np.array([1, 2, 3])
a = bs.State(arr)
print(a.m_data[0])
This is not exactly what I want, but is a step in the right direction.

Related

How can I copy the parameters of one model to another in LibTorch?

How can I copy the parameters of one model to another in LibTorch? I know how to do it in Torch (Python).
net2.load_state_dict(net.state_dict())
I have tried with the code below in C++ with quite a bit of work. It didn't copy one to another.
I don't see an option to copy the parameters of one like model into another like model.
#include <torch/torch.h>
using namespace torch::indexing;
torch::Device device(torch::kCUDA);
void loadstatedict(torch::nn::Module& model, torch::nn::Module& target_model) {
torch::autograd::GradMode::set_enabled(false); // make parameters copying possible
auto new_params = target_model.named_parameters(); // implement this
auto params = model.named_parameters(true /*recurse*/);
auto buffers = model.named_buffers(true /*recurse*/);
for (auto& val : new_params) {
auto name = val.key();
auto* t = params.find(name);
if (t != nullptr) {
t->copy_(val.value());
} else {
t = buffers.find(name);
if (t != nullptr) {
t->copy_(val.value());
}
}
}
}
struct Critic_Net : torch::nn::Module {
torch::Tensor next_state_batch__sampled_action;
public:
Critic_Net() {
lin1 = torch::nn::Linear(3, 3);
lin2 = torch::nn::Linear(3, 1);
lin1->to(device);
lin2->to(device);
}
torch::Tensor forward(torch::Tensor next_state_batch__sampled_action) {
auto h = next_state_batch__sampled_action;
h = torch::relu(lin1->forward(h));
h = lin2->forward(h);
return h;
}
torch::nn::Linear lin1{nullptr}, lin2{nullptr};
};
auto net = Critic_Net();
auto net2 = Critic_Net();
auto the_ones = torch::ones({3, 3}).to(device);
int main() {
std::cout << net.forward(the_ones);
std::cout << net2.forward(the_ones);
loadstatedict(net, net2);
std::cout << net.forward(the_ones);
std::cout << net2.forward(the_ones);
}
Your solution with load_state_dict should work if I understand correctly. The problem here is the same as in your previous question : nothing is registered as either parameters or buffers or submodules. Add the register_module calls and it should work fine.
Link to the question
How this class should look like :
struct Critic_Net : torch::nn::Module {
public:
Critic_Net() {
lin1 = register_module("lin1", torch::nn::Linear(427, 42));
lin2 = register_module("lin1", torch::nn::Linear(42, 286));
lin3 = register_module("lin1", torch::nn::Linear(286, 1));
}
torch::Tensor forward(torch::Tensor next_state_batch__sampled_action) {
// unchanged
}
torch::nn::Linear lin1{nullptr}, lin2{nullptr}, lin3{nullptr};
};

boost python shared_ptr + virtual + overriding in python

I would appreciate help making boost-python use a wrapper class I defined for an abstract base class to wrap derived classes.
I have an abstract C++ base class baz, and derived classes foo (not exposed) and bar (exposed to python). There is a factory function returning boost::shared_ptr<baz> pointing to instances of foo, and here I am hoping to get the boost::shared_ptr<baz> from the factory to be wrapped in baz_callback. I would also like to override pure in python, which seems to work for the base class baz (overridden in the mumble python class), but not for the derived class bar (overridden in jungle).
For illustration, I extended an example from the python wiki, see below. All the printouts should have a 1 as second digit, coming from baz_callback::pure, but only the mumble version gets that right. For jungle, the python verion of pure is ignored, and the C++ version used instead.
File override_shared.cc:
#include <boost/python/class.hpp>
#include <boost/python/module_init.hpp>
#include <boost/python/def.hpp>
#include <boost/python/call_method.hpp>
#include <boost/ref.hpp>
#include <boost/utility.hpp>
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/python/pure_virtual.hpp>
using namespace boost::python;
struct baz {
virtual int pure(int) = 0;
int calls_pure(int x) { return pure(x) + 1000; }
};
struct foo : baz {
int pure(int i) { return i+10; };
};
struct bar : baz {
int pure(int i) { return i+30; };
};
struct baz_callback : baz {
baz_callback(PyObject *p) : self(p) {}
int pure(int x) { return 100 + call_method<int>(self, "pure", x); }
PyObject *self;
};
boost::shared_ptr<baz> make_foo()
{
return boost::shared_ptr<foo>(new foo());
}
boost::shared_ptr<baz> make_bar()
{
return boost::shared_ptr<bar>(new bar());
}
BOOST_PYTHON_MODULE_INIT(liboverride_shared)
{
class_<baz, boost::shared_ptr<baz_callback>, boost::noncopyable>("baz")
.def("pure", pure_virtual(&baz::pure))
.def("calls_pure", &baz::calls_pure);
class_<bar, bases<baz> >("bar");
def("make_foo", make_foo);
def("make_bar", make_bar);
// I suspect the problem lies here:
register_ptr_to_python< boost::shared_ptr<baz> >();
}
File override_shared.py:
from liboverride_shared import *
f = make_foo()
class mumble(baz):
def pure(self, x): return x + 20
m = mumble()
class jungle(bar):
def pure(self, x): return x + 40
j = jungle()
def check(name, bar, i, expected):
actual = bar.calls_pure(i)
msg = "ok" if actual == expected else ("bad, expected %d" % expected)
print (name, actual, "--", msg)
check("foo", f, 1, 1111)
check("mumble", m, 2, 1122)
check("jungle", j, 4, 1144)
File CMakeLists.txt:
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
FIND_PACKAGE(PythonInterp 3 REQUIRED)
FIND_PACKAGE(PythonLibs "${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}" REQUIRED)
FIND_PACKAGE(Boost 1.58.0 REQUIRED COMPONENTS "python-py${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}")
INCLUDE_DIRECTORIES(${PYTHON_INCLUDE_DIRS})
ADD_LIBRARY(override_shared SHARED
override_shared.cc
)
TARGET_LINK_LIBRARIES(override_shared ${Boost_LIBRARIES} ${PYTHON_LIBRARIES})

How to Listen Keys in JScript.Net

What I wish is to catch the keypress using JScript .NET, and compile the code using that jsc.exe.
So, is there any equivalent of "addEventListener("keyDown", keyCheck)" from FLASH actionscript. Or GetAsyncKeyState() from C++.
And what library do I have to use?
Please be kind enough to share a small, simple example.
Here's a simple solution if you're writing a console app.
import System;
Console.Write("Press the M key... ");
var key:ConsoleKeyInfo;
while (1) {
while (!Console.KeyAvailable) {
System.Threading.Thread.Sleep(1);
}
key = Console.ReadKey(1);
if (key.Key == ConsoleKey.M) break;
}
Console.Write("Accepted.");
Read more about ConsoleKeyInfo.
If you need GetAsyncKeyState(), it is possible to access the method in JScript.NET. A couple days ago I came across a JScript.NET function that exposes Win32 API methods via P/Invoke. Here it is, slightly modified for simpler syntax (allowing pass-through of arguments from API function definitions).
import System;
import System.Reflection;
import System.Reflection.Emit;
// Invoke a Win32 P/Invoke call.
// credit: http://cx20.main.jp/blog/hello/2013/03/07/hello-win32-api-jscript-net-world/
function InvokeWin32(dllName:String, returnType:Type, methodName:String, params:Object[]) {
var paramTypes:Type[] = new Type[params.length];
for (var i:int in params) {
paramTypes[i] = params[i].GetType();
}
// Begin to build the dynamic assembly
var domain = AppDomain.CurrentDomain;
var name = new System.Reflection.AssemblyName('PInvokeAssembly');
var assembly = domain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
var module = assembly.DefineDynamicModule('PInvokeModule');
var type = module.DefineType('PInvokeType',TypeAttributes.Public
+ TypeAttributes.BeforeFieldInit);
// Define the actual P/Invoke method
var method = type.DefineMethod(methodName, MethodAttributes.Public
+ MethodAttributes.HideBySig + MethodAttributes.Static +
MethodAttributes.PinvokeImpl, returnType, paramTypes);
// Apply the P/Invoke constructor
var ctor = System.Runtime.InteropServices.DllImportAttribute.GetConstructor(
[System.String]
);
var attr = new System.Reflection.Emit.CustomAttributeBuilder(ctor, [dllName]);
method.SetCustomAttribute(attr);
// Create the temporary type, and invoke the method.
var realType = type.CreateType();
return realType.InvokeMember(methodName, BindingFlags.Public + BindingFlags.Static
+ BindingFlags.InvokeMethod, null, null, params);
}
With this function, you can expose Win32 DLL methods with the following syntax. (See? Told you it was simpler.)
// ShowWindowAsync(hWnd:IntPtr, nCmdShow:int);
function ShowWindowAsync(... args:Object[]):boolean {
return InvokeWin32("user32.dll", System.Boolean, "ShowWindowAsync", args);
}
// GetWindowLong(hWnd:IntPtr, nIndex:int);
function GetWindowLong(... args:Object[]):int {
return InvokeWin32("user32.dll", System.Int32, "GetWindowLong", args);
}
// FindWindowEx(parentHandle:IntPtr, childAfter:IntPtr,
// lclassName:IntPtr, windowTitle:String);
function FindWindowEx(... args:Object[]):IntPtr {
return InvokeWin32("user32.dll", System.IntPtr, "FindWindowEx", args);
}
And I've never used GetAsyncKeyState(); but since it's a user32.dll method, I'm guessing it'll work the same way. (Edit: It does.)
// GetAsyncKeyState(vKey:int);
function GetAsyncKeyState(... args:Object[]):short {
return InvokeWin32("user32.dll", System.Int16, "GetAsyncKeyState", args);
}
Then for a trivial example:
import System; // for Console methods
import System.Windows.Forms; // for Keys object constants
Console.Write("Press the M key... ");
// while the M key is not being pressed, sleep
while (!GetAsyncKeyState(Keys.M)) {
System.Threading.Thread.Sleep(1);
}
// flush input buffer
while (Console.KeyAvailable) Console.ReadKey(1);
Console.WriteLine("Accepted.");

`inline` and `register` modules options

What do --modules inline and --modules register options do?
https://github.com/google/traceur-compiler/wiki/Options-for-Compiling.
Using 2ality.com's lib.js example module:
//------ lib.js ------
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
//------ main.js ------
import { square, diag } from 'lib';
console.log(square(11)); // 121
console.log(diag(4, 3)); // 5
inline wraps the module in an anonymous function, assigned to an auto-generated variable by the looks, it would be interesting to know what this is all about, the technique can be used to bundle modules without actually using a module system, but the var assigned the object returned would have to be known:
var $__src_47_lib_46_js__ = (function() {
"use strict";
var __moduleName = "src/lib.js";
var sqrt = Math.sqrt;
function square(x) {
return x * x;
}
function diag(x, y) {
return sqrt(square(x) + square(y));
}
return {
get sqrt() {
return sqrt;
},
get square() {
return square;
},
get diag() {
return diag;
}
};
})();
//# sourceMappingURL=lib.js.map
System.register is a draft module format:
System.registerModule("src/lib.js", [], function() {
"use strict";
var __moduleName = "src/lib.js";
var sqrt = Math.sqrt;
function square(x) {
return x * x;
}
function diag(x, y) {
return sqrt(square(x) + square(y));
}
return {
get sqrt() {
return sqrt;
},
get square() {
return square;
},
get diag() {
return diag;
}
};
});
System.get("src/lib.js" + '');
//# sourceMappingURL=lib.js.map
Once the module has been registered, then the System.module( ... ) can be called to load the module. Currently I know traceur (though not the runtime) has the System object polyfilled, presumably also babel.
The System.register format has some useful advantages I would suggest, more than one module can be included in a file which suits a collection of smaller closely coupled modules (typically classes); there is no need to buy in to another module system, e.g., including vanilla JS (test data, shims attached to the global object, etc.) in a node module requires additional boilerplate code adding overhead to the workflow, etc.
The System object though is technology still in development (not included the current draft standard).

How to expose aligned class with boost.python

When trying to expose aligned class like this:
class __declspec(align(16)) foo
{
public:
void foo_method() {}
};
BOOST_PYTHON_MODULE(foo_module)
{
class_<foo>("foo")
.def("foo_method", &foo::foo_method);
}
You end up with error (msvs 2010):
error C2719: 'unnamed-parameter': formal parameter with __declspec(align('16')) won't be aligned,
see reference to class template instantiation 'boost::python::converter::as_to_python_function<T,ToPython>' being compiled
The solution I found so far, is to use smart pointer to store object:
BOOST_PYTHON_MODULE(foo_module)
{
class_<foo, boost::shared_ptr<foo>, boost::noncopyable>("foo")
.def("foo_method", &foo::foo_method);
}
Isn't there a better solution? This is quite annoying, because you should wrap all your functions returning objects by value to return smart pointers instead, and performance also degrades.
I had the same problem and wanted a solution that doesn't involve shared_ptr. It involves specializing some boost::python classes to make sure we get a storage area big enough to be able to align our object within it.
I have written a somewhat long blog post explaining how I arrived at this solution here. Below is the solution I found. I feel it is quite a hack, so maybe it will break other things. But so far it seems to work and I haven't found anything better.
I was trying to expose an Eigen::Quaternionf (which requires 16 bytes alignment) :
bp::class_<Quaternionf>("Quaternion", bp::init<float, float, float, float>())
.def(bp::init<Matrix3f>())
.add_property("w", get_prop_const(&Quaternionf::w))
.add_property("x", get_prop_const(&Quaternionf::x))
.add_property("y", get_prop_const(&Quaternionf::y))
.add_property("z", get_prop_const(&Quaternionf::z))
.def("matrix", &Quaternionf::matrix)
.def("rotvec", &quaternion_to_rotvec);
The solution involves specializing 3 classes :
boost::python::objects::instance to request 16 bytes more than what our type requires to ensure we can align
...
union
{
align_t align;
char bytes[sizeof(Data) + 16];
} storage;
...
boost::python::objects::make_instance_impl to correctly set the Py_SIZE of our instance
...
Holder* holder = Derived::construct(
&instance->storage, (PyObject*)instance, x);
holder->install(raw_result);
// Note the position of the internally-stored Holder,
// for the sake of destruction
// Since the holder not necessarily allocated at the start of
// storage (to respect alignment), we have to add the holder
// offset relative to storage
size_t holder_offset = reinterpret_cast<size_t>(holder)
- reinterpret_cast<size_t>(&instance->storage)
+ offsetof(instance_t, storage);
Py_SIZE(instance) = holder_offset;
...
boost::python::objects::make_instance so that the construct method will align the holder in the storage
...
static inline QuaternionfHolder* construct(void* storage, PyObject* instance, reference_wrapper<Quaternionf const> x)
{
// From the specialized make_instance_impl above, we are guaranteed to
// be able to align our storage
void* aligned_storage = reinterpret_cast<void*>(
(reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16);
QuaternionfHolder* new_holder = new (aligned_storage)
QuaternionfHolder(instance, x);
return new_holder;
}
...
The full code is below :
typedef bp::objects::value_holder<Eigen::Quaternionf> QuaternionfHolder;
namespace boost { namespace python { namespace objects {
using namespace Eigen;
//template <class Data = char>
template<>
struct instance<QuaternionfHolder>
{
typedef QuaternionfHolder Data;
PyObject_VAR_HEAD
PyObject* dict;
PyObject* weakrefs;
instance_holder* objects;
typedef typename type_with_alignment<
::boost::alignment_of<Data>::value
>::type align_t;
union
{
align_t align;
char bytes[sizeof(Data) + 16];
} storage;
};
// Adapted from boost/python/object/make_instance.hpp
//template <class T, class Holder, class Derived>
template<class Derived>
struct make_instance_impl<Quaternionf, QuaternionfHolder, Derived>
{
typedef Quaternionf T;
typedef QuaternionfHolder Holder;
typedef objects::instance<Holder> instance_t;
template <class Arg>
static inline PyObject* execute(Arg& x)
{
BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >));
PyTypeObject* type = Derived::get_class_object(x);
if (type == 0)
return python::detail::none();
PyObject* raw_result = type->tp_alloc(
type, objects::additional_instance_size<Holder>::value);
if (raw_result != 0)
{
python::detail::decref_guard protect(raw_result);
instance_t* instance = (instance_t*)raw_result;
// construct the new C++ object and install the pointer
// in the Python object.
//Derived::construct(&instance->storage, (PyObject*)instance, x)->install(raw_result);
Holder* holder = Derived::construct(
&instance->storage, (PyObject*)instance, x);
holder->install(raw_result);
// Note the position of the internally-stored Holder,
// for the sake of destruction
// Since the holder not necessarily allocated at the start of
// storage (to respect alignment), we have to add the holder
// offset relative to storage
size_t holder_offset = reinterpret_cast<size_t>(holder)
- reinterpret_cast<size_t>(&instance->storage)
+ offsetof(instance_t, storage);
Py_SIZE(instance) = holder_offset;
// Release ownership of the python object
protect.cancel();
}
return raw_result;
}
};
//template <class T, class Holder>
template<>
struct make_instance<Quaternionf, QuaternionfHolder>
: make_instance_impl<Quaternionf, QuaternionfHolder, make_instance<Quaternionf,QuaternionfHolder> >
{
template <class U>
static inline PyTypeObject* get_class_object(U&)
{
return converter::registered<Quaternionf>::converters.get_class_object();
}
static inline QuaternionfHolder* construct(void* storage, PyObject* instance, reference_wrapper<Quaternionf const> x)
{
LOG(INFO) << "Into make_instance";
LOG(INFO) << "storage : " << storage;
LOG(INFO) << "&x : " << x.get_pointer();
LOG(INFO) << "&x alignment (0 = aligned): " << (reinterpret_cast<size_t>(x.get_pointer()) & 0xf);
// From the specialized make_instance_impl above, we are guaranteed to
// be able to align our storage
void* aligned_storage = reinterpret_cast<void*>(
(reinterpret_cast<size_t>(storage) & ~(size_t(15))) + 16);
QuaternionfHolder* new_holder = new (aligned_storage) QuaternionfHolder(instance, x);
LOG(INFO) << "&new_holder : " << new_holder;
return new_holder;
//return new (storage) QuaternionfHolder(instance, x);
}
};
}}} // namespace boost::python::objects