Python 3 has many changes to the C API, including in the API for defining classes and initializing modules. This means that every single C extension has to be modified to run under Python 3. Some of the changes are simple and some are not, but you will have to do them all by hand as 2to3 only handles Python code. That also means that you can’t support Python 2 and Python 3 by 2to3 conversion. Luckily the the C pre-processor make it fairly easy to support both Python 2 and Python 3 from the same code. This is a standard way of supporting different versions of API’s in C it will be standard fare for C-programmers. So there are no ugly hacks involved, just some less than pretty #if and #ifndef statements.
There are some things you can do before you start the actual work of adding Python 3 support. The first one is to remove any usage of some old aliases you don’t need any more. For example the RO macro has been removed. It was only a shorthand for READONLY , so if you used RO in your code you can replace it with READONLY instead.