Instantiate wrapper class from C++ - c++

i have wrapped a simple c++ interface / class using pybind11
py::class_<IBaseObject, SmartPtr<IBaseObject>>(m, "BaseObject")
.def(py::init([]()
{
return BaseObject_Create();
}))
)
IBaseObject is interface, SmartPtr is custom holder type and BaseObject_Create is factory function which returns IBaseObject*.
Instatiating class from python works fine, however i also want to instantiate python wrapper class from C++ while passing IBaseObject* as parameter. Is this possible?

If you just want to instantiate your class in your C++ binding code, you can use pybinds Python C++ Interface:
https://pybind11.readthedocs.io/en/stable/advanced/pycpp/object.html#calling-python-functions
Some ways to do this:
// Option 1: Use your existing class handle.
py::class_<IBaseObject, ...> py_cls(...);
py::object py_obj = py_cls();
// - Cast it if you need to.
auto* obj = py_obj.cast<IBaseObject*>();
// - or cast to `SmartPtr<IBaseObject>()` if its shareable.
// Option 2: Re-import elsewhere in your code.
py::object py_cls = py::module::import("my_pybind_module").attr("IBaseObject");
py::object py_obj = py_cls();
// - etc...
// Option 3: Use `eval` (blech)
py::module m = py::module::import("my_pybind_module");
py::object py_obj = py::eval("IBaseObject()", /* globals */ m.attr("__dict__"));

Related

Using spy to mock a full object created in the class which is tested

I have the following structure:
class A {
public A(String p){
// ...
}
public String AMethod(String p){
// ...
}
}
class B {
int method(String param){
A a = new A(param); int n;
String s = A.AMethod(param);
// ... (initializes n, ...)
return n;
}
}
Now I want to test method in class B but control the output of AMethod when it is called. But since I do not create the object A in the test class of B, I cannot mock it normally - how can I mock object A instead?
I tried Mockito.spy but it doesn't seem to work:
this.ASpy = spy(new A());
when(ASpy.createSession(any())).then(invocation -> {
// ... (*)
});
(*) still doen't get called... but spy should be the right solution, shouldn't it? My problem is: I never create an object A in my test class, only in method such an object is created but not in the test class.
The best way to handle this (if possible) would be to modify the code of class B so that object A was injected into the method (passed as a parameter, set as a class field or instantiated with usage of a factory class - the factory would be injected as a field and the factory object could be mocked in the test to return a mocked object A).
If actual code modifications are not possible, you could use PowerMock's whenNew method and return a mocked object in your test.
A side note: if you're using JUnit 5, PowerMock may not be a viable solution - read more here.

Accessing instance variables of a class from pybind11 wrappers

I haven't found a way to do a fairly simple thing with pybind11. Suppose I have an aggregated class, and I want to get to an instance variable of a class so I can drill down into it:
struct foo {
int x;
};
struct baz {
foo var;
}
PYBIND11_MODULE(test, m) {
py::class_<baz>(m, "baz")
.def(py::init<>())
.def("GetX", /* need a lambda to return var.x */ )
;
}
I haven't found anything in the docs which does this, and it seems like an obvious thing to do. I could create accessor methods in baz, but that is extra work. I'd like to do it in a lambda in the wrapper code.
The following lambda creates the necessary GetX member function, which expects one argument: a baz instance. The argument is supplied by pybind11 when GetX is called on an instance of the wrapper class.
...
.def("GetX", [](const baz &b) { return b.var.x; });
Usage:
>>> import ex
>>> v = ex.baz()
>>> v.GetX()
0
See also the pybind11 doc section on binding lambda functions.

How to get all class attr names from derived class using boost::python?

I want to implement and use some class Base. In Python it would be like that:
class Base:
def Enumerate(self):
d = []
for attr in dir(self):
if not attr.startswith('__') and not callable(getattr(self, attr)):
d.append(attr)
return d
class One(Base):
hello = "world"
class Two(Base):
foo = "bar"
arr = [One(), Two()]
arr[0].Enumerate()
arr[1].Enumerate()
But I want to implement Base class in C++ using boost::python.
I've googled a lot, but didn't found anything. Looks like something related to boost::python::wrapper.
Could someone point me the way of how it could be done?
If you are not familiar with Boost.Python, then the tutorial is a good place to start. Beyond that, the reference is a great resource, but requires some experience and can be a bit intimidating or esoteric. Additionally, Boost.Python does not provide convenience functions for the entire Python/C API, requiring developers to occasionally code directly to the Python/C API.
Here is a complete Boost.Python example with python code noted in the comments:
#include <boost/python.hpp>
#include <boost/python/stl_iterator.hpp>
/// #brief dir() support for Boost.Python objects.
boost::python::object dir(boost::python::object object)
{
namespace python = boost::python;
python::handle<> handle(PyObject_Dir(object.ptr()));
return python::object(handle);
}
/// #brief callable() support for Boost.Python objects.
bool callable(boost::python::object object)
{
return 1 == PyCallable_Check(object.ptr());
}
class base {};
/// #brief Returns list of an object's non-special and non-callable
/// attributes.
boost::python::list enumerate(boost::python::object object)
{
namespace python = boost::python;
python::list attributes; // d = []
typedef python::stl_input_iterator<python::str> iterator_type;
for (iterator_type name(dir(object)), end; // for attr in dir(self):
name != end; ++name)
{
if (!name->startswith("__") // not attr.startswith('__')
&& !callable(object.attr(*name))) // not callable(getattr(self, attr))
attributes.append(*name); // d.append(attr)
}
return attributes; // return d
}
BOOST_PYTHON_MODULE(example)
{
namespace python = boost::python;
python::class_<base>("Base")
.def("Enumerate", &enumerate)
;
}
And its usage:
>>> from example import Base
>>>
>>> class One(Base):
... hello = "world"
...
>>> class Two(Base):
... foo = "bar"
...
>>> arr = [One(), Two()]
>>>
>>> arr[0].Enumerate()
['hello']
>>> arr[1].Enumerate()
['foo']
Although Boost.Python does a great job at providing seamless interoperability between Python and C++, when possible, consider writing Python in Python rather than C++. While this is a simple example, the program gains little or nothing being written in C++. On more extensive examples, it can quickly require attention to very minute details, presenting an interesting challenge to maintain a Pythonic feel.

How to wrap a C++ factory method in a Python __init__ function using SWIG

I'm porting a Python extension module written in C++ from Boost.Python to SWIG.
The C++ code defines an abstract class X with a static factory method
class X {
public:
static X* create(const char* descr);
...
};
The factory method returns a pointer to an instance of some derived class.
With Boost.Python you can wrap the C++ class X in a Python class X that has an
__init__(self, descr)
method that calls X::create. In fact, it is done as follows:
namespace bp = boost::python;
bp::class_<X>("X", boost::no_init)
.def("__init__", bp::make_constructor(&X::create))
...
Is there a way of doing the same thing with SWIG?
As suggested, it is better to use __new__ for controlling how a class is created. In SWIG, you should create an interface (.i) file that looks as follows:
%extend X {
static X * __new__(const char *desc) { return create(desc); }
};

Why aren't type parameters allowed in Scala auxiliary constructors?

Say I'm defining a simple 2D point class in Scala, and I want to be able to construct it with various types:
class Point(x:Float, y:Float) {
this(x:Double, y:Double) = this(x.toFloat, y.toFloat)
this(x:Int, y:Int) = this(x.toFloat, y.toFloat)
// etc...
}
I want to boil this down using a template, such as:
class Point(x:Float, y:Float) {
this[T](x:T, y:T) = this(x.toFloat, y.toFloat)
}
I know this won't work anyway, since T could be a type for which toFloat isn't defined, but the compiler error I get is:
no type parameters allowed here
Is this just unsupported in Scala? If so, why, and is there any simple way to get around this?
Scala's class constructors (unlike Java's) can't take type parameters, only the class itself can. As to why Scala made this design choice, I assume the main reason is simplicity.
If you want a secondary "builder" method that is generic, the natural thing to do is define it on the companion object. For example,
object Point {
def build[T : Numeric](x: T, y: T) = {
val n = implicitly[Numeric[T]]
new Point(n.toFloat(x), n.toFloat(y))
}
}
class Point(val x:Float, val y:Float)
val p = Point.build(1, 2) // Companion object's builder
p.x + p.y
Here I've used the Numeric typeclass to get a generic toFloat method.
I played with this for awhile, getting as "close" as...
class Point(x:Float, y:Float) {
def this[T <: Any { def toFloat: Float }](x:T, y:T) = this(x.toFloat, y.toFloat)
}
...which results in "error: no type parameters allowed here" (just as per the post) and then I realized...
If the initializer could take type parameters it would be ambiguous with the class parameters, if any. Not that this couldn't be worked about in the language specification... but it is a more complex case at the very least. There might also be Java interoperability issues.
Imagine:
class Foo[T](x: T) {
def this[X](z: X) = ...
}
new Foo[Int](42) // T is Int? X is ...? Or ...?
Personally I wish Scala followed an Eiffel-like pattern (only named constructors or "factory methods"), but alas, that would not be Scala.
Happy coding.