this is basic C++ but I am getting to a point where python actually seems way simpler. Suppose:
class Base
{
public:
virtual ~Base() = default;
virtual std::string type() const { return "base"; };
};
class Derived1 : public Base
{
public:
virtual std::string type() const { return "dervied1"; };
};
class Derived2 : public Base
{
public:
virtual std::string type() const { return "dervied2"; };
};
I find my self having other functions of type:
void process(Base& derived_from_base)
{
};
Q1: How do I know what I am taking as input, should I call type() and later down cast, problem is I think type() will give always "base"?
Q2: This is so annoying. I later have to down case the input to the correct derived class. I am just wondering if python is doing this in the background, am I sure that with all of this I am faster than python?
Q3: Is it true I can replace virtual function/inheritance and all casting using templates? (heard this somewhere and not sure).
Thank you very much.
Q1: How do I know what I am taking as input?
A1: Keep the full type instead of erasing it to the base class. E.g. instead of
void process(Base& base) {
if (base.type() == "derived1") process_derived1(static_cast<Derived1&>(base));
else process_anything_else(base);
}
int main() {
std::unique_ptr<Base> base = std::make_unique<Derived1>();
process(*base);
}
use
void process(Derived1& derived1) { process_derived1(derived1); }
void process(auto& t) { process_anything_else(t); }
int main() {
Derived derived1;
process(derived1);
}
Q2: I am just wondering if python is doing this in the background, am I sure that with all of this I am faster than python?
A2: Python has something like this:
int main() {
Object derived1; // a hash map
derived1["__type__"] = "Derived1";
}
With the approach from A1, you are faster than anything (assuming everything else in the program isn't worse) because of static dispatch: thanks to templates, overload resolution happens at compile time and therefore costs nothing.
Q3: Is it true I can replace virtual function/inheritance and all casting using templates? (heard this somewhere and not sure)
A3: With proper design, you can do that most of the times, e.g. see A1. However, some things force linking dynamically: OS API, game plugins etc. In such cases, consider localizing the clumsy borderline part, so most of the code can be written as usual.
virtual function/inheritance
Note: inheritance without virtual functions is perfectly fine and zero-cost (on its own), e.g. see CRTP.
Related
As is also explained in this cppyy issue, an A& operator() on the C++ side is mapped to the python __getitem__.
On the issue it is suggested to add a special pythonization if this is not the wished for result.
An extra constraint in my case would be to add this to the C++ class itself to ensure that this pythonization is always applied.
I'm however having trouble figuring out how to properly do this via the Python C API. (1st time working with the that API so I'm a bit lost)
Minimal Reproducer somewhat contrived but shows the problem:
Note in the example below that struct A is code that I can't modify because that class is defined in library code. So the callback has to be in B.
import cppyy
cppyy.include("Python.h")
cppyy.cppdef(r"""
void myprint(PyObject* py){
PyObject* tmp = PyObject_Str(py);
Py_ssize_t size = 0;
const char* s = PyUnicode_AsUTF8AndSize(tmp, &size);
std::cout << std::string(s, size) << std::endl;
}
template <typename T>
struct A {
T& operator[](size_t idx) { return arr[idx]; }
const T& operator[](size_t idx) const { return arr[idx]; }
std::array<T, 10> arr{};
};
template <typename T>
struct B : public A<T> {
B& operator()() { return *this; };
static void __cppyy_pythonize__( PyObject* klass, const std::string& name){
std::cout << "Hello from pythonize" << std::endl;
PyObject* getitem = PyObject_GetAttrString(klass, "__getitem__");
myprint(getitem);
}
};
using tmp = B<double>;
""")
t = cppyy.gbl.B['double']
print(t.__getitem__.__doc__)
I can get the __getitem__ function from the PyObject* klass but, as explained in the docs, the callback happens at the very end after all the internal processing of the class.
Thus the __call__ function, which here is B& operator()(), has already been mapped to __getitem__.
Unfortunately, I can't for the life of me figure out how I would undo that mapping and get back that old __getitem__ function.
Is that operator[]() function even still accessible via the PyObject* klass ?
Any help/pointers would be much appreciated :)
First, to answer your question, to find the __getitem__ you want, get it from the base class of klass, not from klass directly. You can also do this in Python, rather than adding pythonizations in C++. In fact, doing this in Python is preferred as then you don't have to deal with the C-API.
However, since the actual bug report is not the one you referenced, but this one, and since the suggestion made there, which you followed here, makes this a classic XY-problem, let me also add that what you really want is to simply do PyObject_DelAttrString(klass, "__getitem__") in your code example.
Completely aside, the code that is giving you trouble here is from the Gaudi project, the core developers of which are the ones who asked for this automatic mapping in the first place. You may want to take this up with them.
So, I know that pybind lets you set a return value policy for methods that you wrap up. However, that doesn't seem to be working for me when I try to use this policy on a constructor. I have a class to wrap my C++ type that looks like this:
class PyComponent{
public:
static Component* Create(ComponentType type) {
Component* c = new Component(type);
// Irrelevant stuff removed here
return c;
}
/// #brief Wrap a behavior for Python
static void PyInitialize(py::module_& m);
};
void PyComponent::PyInitialize(py::module_ & m)
{
py::class_<Component>(m, "Component")
.def(py::init<>(&PyComponent::Create), py::return_value_policy::reference)
;
}
However, this does NOT stop my Component type from getting deallocated from the Python side if I call Component() and the created object goes out of scope. Any suggestions?
I did figure out the solution to this. It's to pass py::nodelete to the wrapper for my class
void PyComponent::PyInitialize(py::module_ & m)
{
py::class_<Component, std::unique_ptr<Component, py::nodelete>>(m, "Component")
.def(py::init<>(&PyComponent::Create), py::return_value_policy::reference)
;
}
In my specific circumstance, I have a complex class (a class of classes of classes) that I want to expose to a scripting language (aka Ruby). Rather that directly pass that complex class, someone gave me the idea of just opening up a few functions to a scripting language like Ruby, which seemed simpler. I've seen Rice but the only examples I've seen use simple functions that just multiply something, rather than interfacing with a class.
For simplicity, I have a simple class with functions I want to expose:
class Foo
{
private:
//Integer Vector:
std::vector<int> fooVector;
public:
//Functions to expose to Ruby:
void pushBack(const int& newInt) {fooVector.push_back(newInt);}
int& getInt(const int& element) {return fooVector.at(element);}
};
ALSO:
I'd prefer not to just have a link to the download page of SWIG, or an article explaining how to do this with rice that was written in 2010, I would like a guide that will likely work (I haven't had much luck just yet)
ASWELL:
I'm using Linux (Ubuntu) but this is a cross-compatible program, so I must be able to compile on Windows and OS X
EDIT:
I do understand that shared libraries exist (dll and so files), but I don't know if I can have a library that depends on a .hpp file containing the class(es).
You can use cython or Boost.Python to call native code from python. Since you are using c++, i'd recommend looking into Boost.Python which offers a very natural way of wrapping c++ classes for python.
As an example (close to what you provided), consider the following class definitions
class Bar
{
private:
int value;
public:
Bar() : value(42){ }
//Functions to expose to Python:
int getValue() const { return value; }
void setValue(int newValue) { value = newValue; }
};
class Foo
{
private:
//Integer Vector:
std::vector<int> fooVector;
Bar bar;
public:
//Functions to expose to Python:
void pushBack(const int& newInt) { fooVector.push_back(newInt); }
int getInt(const int& element) { return fooVector.at(element); }
Bar& getBar() { return bar; }
};
double compute() { return 18.3; }
This can be wrapped to python using Boost.Python
#include <boost/python.hpp>
BOOST_PYTHON_MODULE(MyLibrary) {
using namespace boost::python;
class_<Foo>("Foo", init<>())
.def("pushBack", &Foo::pushBack, (arg("newInt")))
.def("getInt", &Foo::getInt, (arg("element")))
.def("getBar", &Foo::getBar, return_value_policy<reference_existing_object>())
;
class_<Bar>("Bar", init<>())
.def("getValue", &Bar::getValue)
.def("setValue", &Bar::setValue, (arg("newValue")))
;
def("compute", compute);
}
This code can be compiled to a static library MyLibrary.pyd and used like this
import MyLibrary
foo = MyLibrary.Foo()
foo.pushBack(10);
foo.pushBack(20);
foo.pushBack(30);
print(foo.getInt(0)) # 10
print(foo.getInt(1)) # 20
print(foo.getInt(2)) # 30
bar = foo.getBar()
print(bar.getValue()) # 42
bar.setValue(17)
print(foo.getBar().getValue()) #17
print(MyLibrary.compute()) # 18.3
What about Boost.Python?
How come you don't want to use SWIG?
Firstly, I'm a physicist, so my coding experience and knowledge is limited so apologies if I'm not using the correct terminology or if an answer to this question already exists. I've been unable to find anything sufficiently similar that makes sense to me though.
Now, I'm performing Monte Carlo simulations of some quantum system and within this I need some specific polynomials. I have written classes for all such polynomials. They all take the same arguments when initialising (a string and an integer) and the only public method in all of them is similarly identical from an outward perspective (it takes in an array of complex doubles and outputs one complex double). The general picture is
class Polyi{
public:
Polyi(string type, int N){
::Set things up if needed::
}
complex<double> poly(complex<double> *z){
::Calculate the polynomial and return::
}
}
Now, the polynomial I wish to use in a given simulation needs to be something I can input from the outside. I'm more used to Python so something like
if poly_type==i: polynomial = Polyi(type, N)
elif ...
is what I want to do. I'd then use polynomial.poly(z) in the subsequent code.
However, this is proving extremely difficult in C++ because I have to declare the type of class I'm using at assignment. I've tried a couple of things. I made a handler that contains all the individual polynomials. Didn't work. I also tried to make a base class to all of these including the poly(z) function and then overload it in each. I also fell short here. However, they probably didn't work because I'm an idiot, not because they're actually impossible to implement.
Therefore, how could I implement this kind of dynamic assignment, such that when I hit my actual calculation, I have a the desired polynomial, of whatever class, in the variable polynomial and I can just call polynomial.poly(z)? The most simple solution to this would be awesome if possible, because I'd like to be able to understand what the code is actually doing.
Thanks for any help you can offer me!
EDIT: Thankyou so much to everyone! There wasn't a single unhelpful comment/answer and a lot of great suggestions of things to look up. Thanks to everyone!!!
ps. To clarify, though it didn't seem to be a crucial point, the type variable defines a type of polynomial within a type of polynomial. So for example, for the Pn polynomials, Pn("1",N) = z1+z2+...+zN, Pn("2",N)=z1^2+z2^2+...zN^2 etc. On the more complicated side I have the Jack polynomials, which are indexed by a partition of integers (like 11122 or 223). I have no idea how to generate them so I download a file with them, hence why it's a string.
Polymorphism in C++ relies on pointers.
If you have a base class Poly and then child classes Polya, Polyb, Polyi.. etc.
you can have a Poly* actually pointing to a Polya*, however you cannot have a Poly containing a Polya because you will face type-slicing.
So you can have something like this :
class Poly_base
{
public:
Poly_base(string type, int N) {
// Potentially do stuff that you do on ALL poly
}
virtual complex<double> poly(complex<double> *z) = 0;
}
class Polyi : public Poly_base
{
public:
Polyi(string type, int N):
Poly_base(type, N)
{
// Stuff you would do only on Polyi.
}
virtual complex<double> poly(complex<double> *z)
{
// Your calculation for Polyi.
}
}
NOTE the virtual keyword. This says : here is a method on my base class that can be reimplemented on child classes.
If you call poly on a Poly_base* pointer that is actually pointing to a Polya instance, then the reimplemented version will be called. (via the magic of vtables)
Then in main :
Poly *polynomial;
if (some_condition) {
polynomial = new Polya(type, N);
} else if (some_other_condition) {
polynomial = new Polyi(type, N);
}
polynomial->poly(z);
EDIT: You might want your type to be an enum instead of a string, so you can do a switch statement on it like so :
enum PolyType {
polya = 0,
polyb,
polyi
}
Poly_base *polynomial;
switch (type) {
case polya:
polynomial = new Polya(type, N);
break;
case polyb:
polynomial = new Polyb(type, N);
break;
case ....
}
EDIT2: you also probably don't need the type in your classe constructor.. The whole point of this architecture is that this information is contained in the instance you actually created. If you created a Polya, then it "knows" it is a Polya and not a Polyb.
I'd say this is a perfect place for the factory design pattern.
class iPoly{
public:
virtual ~iPoly(){}
virtual complex<double> poly(complex<double> *z) = 0;
};
class Polyi : public iPoly {
public:
Polyi(string type, int N);
virtual ~Polyi(){}
virtual complex<double> poly(complex<double> *z);
};
class Polyb : public iPoly {
public:
Polyb(string type, int N);
virtual ~Polyb(){}
virtual complex<double> poly(complex<double> *z);
};
iPoly* make_poly(string type, int N) {
if (type=="Polyi") {
return new Polyi(type,N);
} else if (type=="Polyb") {
return new Polyb(type,N);
}
return NULL;
}
I have lots of C/C++ classes to export to python using Swig. I've noticed that by default, Swig doesn't generate a __hash__ method for wrapped classes, so the default hash gets used, which is the id of the wrapper object (i.e. its memory address or something like it). This means if I end up with two python objects wrapping the same C object, they hash differently in dicts and so on, which is weird and leads to hard-to-find bugs.
I can easily extend any class with a better __hash__:
%extend Foo {
bool __eq__(const Foo &other) { return $self == &other; }
bool __ne__(const Foo &other) { return $self != &other; }
long __hash__() { return (long) $self; } // hash: just address of C struct
}
(I also think eq should by default compare based on the C struct address, rather than the wrapper's address.)
My question is this: Is there any way to tell Swig to extend all classes like this? Or do I have to do them one at a time?
I guess a secondary question would be: why doesn't swig just do this automatically? Is the default behavior useful? I don't find it to be.
I am not aware of a way to do that, if only because it is rarely what you would want ("all classes" could include more than you realize and really intended). However, SWIG does support its own macro system, so you could probably do something like:
%define PY_HASHABLE(TypeName)
%extend TypeName {
bool __eq__(const TypeName &other) { return $self == &other; }
bool __ne__(const TypeName &other) { return $self != &other; }
long __hash__() { return (long) $self; } // hash: just address of C struct
}
%enddef
Then you would do
#if defined(SWIGPYTHON)
PY_HASHABLE(Foo)
PY_HASHABLE(Bar)
#endif
etc. You can have multiple extend clauses for a given class so the above does not interfere with other extensions.