Question

I'm creating a Python wrapper over some C++ library implementing some low-level M2M communication. I'm using Riverbank's SIP wrapper generator.

The C++ class has a method:

class Bar {
public:
    enum Status {
        ...
    };
    void setStatus(Status s);
    Status getStatus() const;
    ...
};

The class is contained in module foo.

SIP is using it's own enum type, but for few reasons I'd like to use Python 3.4 enum from standard libray.

I don't see any chance of accessing Python-defined classes from Python C API and I decided to patch wrapped class in __init__.py. The main reason is that I want to make dirty low-level work in C/C++/SIP and polish the class in Python (like add argument validation with sane error messages).

The Python __init__.py part looks like this (more or less):

from foo import Bar

class Status(IntEnum):
    ONE = 1
    TWO = 2
    ... and so on ...
Status.__module__ = 'Bar.Status'
Bar.Status = Status
Bar.status = property(...)

Bar.status will accept and return nice, pythonic Bar.Status enum.

Expected result is something like this:

class Bar(object):
    class Status(IntEnum):
         ...
    ...

I'm wondering if there is anything wrong with this approach, especially with patching the object at import.

Was it helpful?

Solution

I solved the problem in other way that seems to be ok.

Let's consider a C++ library that contains two classes:

  1. Foo
  2. FooFactory

Wrapper library contains package libfoo (created in Python C API) and pythonic package foo (created in ordinary python). We don't access libfoo package directly, but import foo.

Package foo's __init__.py:

from libfoo import Foo, FooFactory

# both are naked wrappers with ugly API derived from C++
# I defined some pythonic sugar that makes them nice to use

class FooPythonicGoodies(object):
    # add pythonic goodies here
    def quack(self):
        pass

# Merge them
Foo.__bases__ = Foo.__bases__ + (FooPythonicGoodies,)

Now, when anywhere in the sources I do this:

from foo import Foo, FooFactory

a = Foo()
a.quack()

# Factory is a C++ wrapped class that returns wrapped foo
# objects WITH FooPythonicGoodies!
factory = FooFactory()
b = factory.create_foo()
b.quack() # that works too!

That way I can polish rather un-pythonic C++ classes with a pythonic API sugar.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top