Skip to content

Commit

Permalink
Minor tidying of file system (.cpp -> .cxx, some .hxx -> .h, creation…
Browse files Browse the repository at this point in the history
… of File.h) and README.md
  • Loading branch information
p-i- committed Feb 17, 2015
1 parent 8208516 commit ebdf428
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 53 deletions.
18 changes: 10 additions & 8 deletions PiCxx.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
0E9A25CF1A8E866900C74356 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0E9A25661A8E825A00C74356 /* main.cpp */; };
0E9A25D01A8E866B00C74356 /* test_funcmapper.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 0E9A25681A8E825A00C74356 /* test_funcmapper.cxx */; };
0E9A25D21A8E867200C74356 /* test_objects.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 0E9A256A1A8E825A00C74356 /* test_objects.cxx */; };
0E9A25D31A8E867600C74356 /* test_prompt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0E9A256B1A8E825A00C74356 /* test_prompt.cpp */; };
0E9A25D31A8E867600C74356 /* test_prompt.cxx in Sources */ = {isa = PBXBuildFile; fileRef = 0E9A256B1A8E825A00C74356 /* test_prompt.cxx */; };
/* End PBXBuildFile section */

/* Begin PBXCopyFilesBuildPhase section */
Expand All @@ -29,9 +29,10 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
0E0F22C81A93694400B02299 /* File.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = File.h; sourceTree = "<group>"; };
0E9A25441A8E818500C74356 /* PiCxx */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = PiCxx; sourceTree = BUILT_PRODUCTS_DIR; };
0E9A25511A8E81CC00C74356 /* Config.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Config.hxx; sourceTree = "<group>"; };
0E9A25521A8E81CC00C74356 /* Debug.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Debug.hxx; sourceTree = "<group>"; };
0E9A25511A8E81CC00C74356 /* Config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Config.h; sourceTree = "<group>"; };
0E9A25521A8E81CC00C74356 /* Debug.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Debug.h; sourceTree = "<group>"; };
0E9A25531A8E81CC00C74356 /* Exception.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Exception.hxx; sourceTree = "<group>"; };
0E9A25541A8E81CC00C74356 /* Base.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Base.hxx; sourceTree = "<group>"; };
0E9A25551A8E81CC00C74356 /* ExtModule.hxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ExtModule.hxx; sourceTree = "<group>"; };
Expand All @@ -50,7 +51,7 @@
0E9A25681A8E825A00C74356 /* test_funcmapper.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_funcmapper.cxx; sourceTree = "<group>"; };
0E9A25691A8E825A00C74356 /* test_funcmapper.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; path = test_funcmapper.py; sourceTree = "<group>"; };
0E9A256A1A8E825A00C74356 /* test_objects.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_objects.cxx; sourceTree = "<group>"; };
0E9A256B1A8E825A00C74356 /* test_prompt.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_prompt.cpp; sourceTree = "<group>"; };
0E9A256B1A8E825A00C74356 /* test_prompt.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = test_prompt.cxx; sourceTree = "<group>"; };
0E9A256D1A8E827400C74356 /* libpython3.4.1_OSX.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libpython3.4.1_OSX.dylib; sourceTree = "<group>"; };
0E9A256F1A8E827400C74356 /* abstract.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = abstract.h; sourceTree = "<group>"; };
0E9A25701A8E827400C74356 /* accu.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = accu.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -209,9 +210,10 @@
0E9A25501A8E81CC00C74356 /* Base */ = {
isa = PBXGroup;
children = (
0E9A25511A8E81CC00C74356 /* Config.hxx */,
0E9A25521A8E81CC00C74356 /* Debug.hxx */,
0E9A25511A8E81CC00C74356 /* Config.h */,
0E9A25521A8E81CC00C74356 /* Debug.h */,
0E9A25531A8E81CC00C74356 /* Exception.hxx */,
0E0F22C81A93694400B02299 /* File.h */,
);
path = Base;
sourceTree = "<group>";
Expand Down Expand Up @@ -246,7 +248,7 @@
0E9A25681A8E825A00C74356 /* test_funcmapper.cxx */,
0E9A25691A8E825A00C74356 /* test_funcmapper.py */,
0E9A256A1A8E825A00C74356 /* test_objects.cxx */,
0E9A256B1A8E825A00C74356 /* test_prompt.cpp */,
0E9A256B1A8E825A00C74356 /* test_prompt.cxx */,
);
path = test_PiCxx;
sourceTree = "<group>";
Expand Down Expand Up @@ -418,7 +420,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0E9A25D31A8E867600C74356 /* test_prompt.cpp in Sources */,
0E9A25D31A8E867600C74356 /* test_prompt.cxx in Sources */,
0E9A25CF1A8E866900C74356 /* main.cpp in Sources */,
0E9A25D01A8E866B00C74356 /* test_funcmapper.cxx in Sources */,
0E9A25D21A8E867200C74356 /* test_objects.cxx in Sources */,
Expand Down
19 changes: 3 additions & 16 deletions PiCxx/headers/Base.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,8 @@
#ifndef PICXX_DEBUG
# define PICXX_DEBUG (1)
#endif
#include "Base/Debug.hxx"
#include "Base/Config.hxx"
#include "Base/Config.h"
#include "Base/Debug.h"
#include "Base/Exception.hxx"
#include "Base/File.h"

namespace Py
{
inline void run_file( const char* filestring )
{
FILE* file = fopen(filestring,"r");

COUT( "\n = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = \n" );
COUT( "Executing File:" << filestring );

COUT( PyRun_SimpleFile(file, filestring) );

fclose( file );
}
}
File renamed without changes.
File renamed without changes.
16 changes: 16 additions & 0 deletions PiCxx/headers/Base/File.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

namespace Py
{
inline void run_file( const char* filestring )
{
FILE* file = fopen(filestring,"r");

COUT( "\n = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = \n" );
COUT( "Executing File:" << filestring );

COUT( PyRun_SimpleFile(file, filestring) );

fclose( file );
}
}
58 changes: 29 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,10 @@ The remainder of this document is a mix of internal / external. For the deep in
headers
Base.hxx
Base
Config.hxx
Debug.hxx
Config.h
Debug.h
Exception.hxx
File.h

Objects.hxx
ExtObj.hxx
Expand Down Expand Up @@ -367,22 +368,22 @@ Other than that, the entire library is headers only. The good thing about that i

headers
Base.hxx
Base
Config.hxx
Debug.hxx
Exception.hxx
Base
Config.h
Debug.h
Exception.hxx
File.h

Base.hxx includes all the headers in /Base in the order in which they are listed.
(Used to be several until I did some pruning)
Base.hxx includes all the headers in `/Base` in the order in which they are listed.
(I use this pattern everywhere).

- - -

Objects.hxx

`Objects.hxx` includes `Base.hxx`

If you just want to make use of stock Python objects, e.g. use a Python Dictionary object, just include Objects.hxx
(but I can't imagine any practical use case like this).
If you just want to make use of stock Python objects, e.g. use a Python Dictionary object, just include `Objects.hxx` (but I can't imagine any practical use case like this).

The `test_objects.cxx` demo does exactly this. Maybe have a look at it before progressing...

Expand All @@ -398,37 +399,38 @@ The `test_objects.cxx` demo does exactly this. Maybe have a look at it before pr
OldStyle.hxx
NewStyle.hxx

If you need extension objects, just include ExtObj.hxx. That will include Objects.hxx and everything in /ExtObj in the correct order (as shown).
If you need extension objects, just include ExtObj.hxx. That will include `Objects.hxx` and everything in `/ExtObj` in the correct order (as shown).

Be aware that Python has old style and new style classes. New style came in with 2.2? Everything is new style for 3.x

Why am I still supporting old-style then? Well, maybe one day someone (maybe me) will extend this to support Python 2.x. It doesn't seem to be dying...

So both OldStyle and NewStyle derive from ExtObject, which itself derives from ExtObjBase. I've added that extra layer just to explicitly separate out the parts of the base that require CRTP
So both `OldStyle` and `NewStyle` derive from `ExtObject`, which itself derives from `ExtObjBase`. I've added that extra layer just to explicitly separate out the parts of the base that require CRTP.

If you look at ExtObjBase, you will see it has a ton of virtual methods -- each one corresponds to a slot on the function-pointer table of a PyTypeObject (look in TypeObject.hxx)
If you look at `ExtObjBase`, you will see it has a ton of virtual methods -- each one corresponds to a slot on the function-pointer table of a `PyTypeObject` (look in `TypeObject.hxx`)

For a custom extension object, every time Python runtime makes a new instance of it, in C++ land we must make an instance of a corresponding C++ class (deriving from OldStyle or NewStyle)
For a custom extension object, every time Python runtime makes a new instance of it, in C++ land we must make an instance of a corresponding C++ class (deriving from `OldStyle` or `NewStyle`)

When the Python runtime invokes some slot from this PyObject's PyTypeObject, (i.e. the slot contains a pointer to a function, so say Python runtime calls this function) this must result in a corresponding function getting invoked on this C++ object
When the Python runtime invokes some slot from this `PyObject`s `PyTypeObject`, (i.e. the slot contains a pointer to a function, so say Python runtime calls this function) this must result in a corresponding function getting invoked on this C++ object.

Bridge is the structure that binds the PyObject to the C++ object. You will notice that Bridge is only used new style classes. Old-style classes have PyObject as base-class, so the same memory location doubles as the PyObject and the bass class of the C++ object.
`Bridge` is the structure that binds the `PyObject` to the C++ object. You will notice that `Bridge` is only used new style classes. Old-style classes have `PyObject` as base-class, so the same memory location doubles as the `PyObject` and the bass class of the C++ object.

New style classes can't use this trick as the size of the PyObject isn't guaranteed, because for new style classes, we allow within Python derivation. And the derived class may have a bigger footprint.
New style classes can't use this trick as the size of the `PyObject` isn't guaranteed, because for new style classes, we allow within-Python derivation. And the derived class may have a bigger footprint.

***TODO**: currently the new-style class still has a PyObject base which is unused. **Get rid of this!***

- - -

ExtModule.hxx

If you need an extension module, include only ExtModule.hxx, which will include ExtObj.hxx. And I can't think of any situation where you wouldn't do this. You stick your extension objects in an extension module. From Python you import the module and can then access the contained objects.
If you need an extension module, include only `ExtModule.hxx`, which will include `ExtObj.hxx`. And I can't think of any situation where you wouldn't do this. You stick your extension objects in an extension module. From Python you import the module and can then access the contained objects.

So what does FuncMapper do? I'm documenting it here because it applies to both extension modules and extension classes. It's possible to write functions for an extension module or an extension object.
So what does `FuncMapper` do? I'm documenting it here because it applies to both extension modules and extension classes. It's possible to write functions for an extension module or an extension object.

So the user, in Python, does something like `myModule.myFunc()` of `myObj.myFunc(arg,kw)` (etc), and Python will perform a lookup on `myFunc` and invoke its associated function pointer. πcxx needs to supply a function that will trampoline to a corresponding method in the module/object's C++ class.

FuncMapper handles this trampolining.
`FuncMapper` handles this trampolining.

The mechanism is slightly different for {old-style classes & modules} and {new-style classes}, but there is enough in common to warrant a single mechanism.

- - -
Expand All @@ -444,16 +446,15 @@ The mechanism is slightly different for {old-style classes & modules} and {new-s

Test suite! At the moment this is not very comprehensive, but it should give some idea how to use πcxx. It's probably best to start here when browsing through the source code.

test_assert.hxx is a helper (currently unused)
`test_assert.hxx` is a helper (currently unused)

main.cpp allows you to toggle which of the tests you wish to run
`main.cpp` allows you to toggle which of the tests you wish to run

test_objects.cxx -- it's important to understand this one, because everything else makes use of this Object class.
`test_objects.cxx` -- it's important to understand this one, because everything else makes use of this Object class.

test_funcmapper.* tests extension module and classes (old&new style).
Initialisation, trampolining of function calls, destruction.
`test_funcmapper.*` tests extension module and classes (old&new style). Initialisation, trampolining of function calls, destruction.

test_prompt.cpp creates a interactive Python terminal prompt in XCode's console output Sometimes it's helpful to spawn this prompt in the middle of some other test. This way we can inspect the state of the Python Runtime.
`test_prompt.cpp` creates a interactive Python terminal prompt in XCode's console output Sometimes it's helpful to spawn this prompt in the middle of some other test. This way we can inspect the state of the Python Runtime.


## Walkthroughs:
Expand Down Expand Up @@ -505,10 +506,9 @@ Special thanks to the wonderful people on Freenode, especially Yhg1s on #python


## Final notes:
In a few places I've demonstrated some C++ constructs using geordi
Google "Geordi Eelis". You can use Geordi for testing out C++ constructs on the FreeNode IRC server, #geordi
In a few places I've demonstrated some C++ constructs using geordi. Google *"Geordi Eelis"*. You can use Geordi for testing out C++ constructs on the FreeNode IRC server, #geordi

I recommend looking in `test_prompt.cpp` first, then looking in main, then looking at `test_funcmapper.*`. Setting breakpoints and single-stepping through the code should reveal how the library works.
I recommend looking in `test_prompt.cpp` first, then `main.cpp`, then `test_objects.hxx`, then `test_funcmapper.*`. Setting breakpoints and single-stepping through the code should reveal how the library works.

However, it's very difficult for me (now that I understand the problem) to provide good documentation. Because reading and writing documentation is a linear process, And something like this is a connected web of moving parts. So it's a challenge to present everything in some sensible order that builds up from the ground without any holes. I'm hoping that in the future, other people seeking to understand the library will shine some light through these holes so that they can be patched up.

Expand Down
File renamed without changes.

0 comments on commit ebdf428

Please sign in to comment.