C++ Design Issues
Using Python as a glue logic facility necessarily imposes a number of design requirements on your C++ code:
- Good error-handling and exception management
- Correct memory management
- Correct disk I/O management
In other words, if you call bad C++ code from within Python glue logic, the result won't be any better than calling the C++ code directly! Listing 5 illustrates the C++ code used earlier.
Listing 5The C++ code invoked using Python.
#include <iostream> #include <string.h> #define MEMORY_BLOCK_SIZE 30 #include "Person.h" using namespace std; void printABlock(string blockName, char *block, int size) { cout << blockName << " = "; for (int i = 0; i < size; i++) { cout << block[i]; } cout << endl; } void doSomeMemoryWork() { cout << endl << "Function name: "<< __func__ << "()"<< endl; char* a = (char*)malloc(MEMORY_BLOCK_SIZE); memset(a, 'a', MEMORY_BLOCK_SIZE); char* b = (char*)malloc(MEMORY_BLOCK_SIZE); memset(b, 'b', MEMORY_BLOCK_SIZE); char* c = (char*)malloc(MEMORY_BLOCK_SIZE);; memset(c, 'c', MEMORY_BLOCK_SIZE); cout << "Before memory assignment" << endl; printABlock("a", a, MEMORY_BLOCK_SIZE); printABlock("b", b, MEMORY_BLOCK_SIZE); printABlock("c", c, MEMORY_BLOCK_SIZE); // Before re-assignment of a, free its allocated memory free(a); a = b; cout << "After memory assignment" << endl; printABlock("a", a, MEMORY_BLOCK_SIZE); printABlock("b", b, MEMORY_BLOCK_SIZE); printABlock("c", c, MEMORY_BLOCK_SIZE); free (b); free (c); } unique_ptr<Person> createPerson() { unique_ptr<Person> p(new Person("John Doe", 100)); cout << "Person just created is: " << p->getName() << endl; return p; } void getPersonDetails() { unique_ptr<Person> person = createPerson(); cout << "Person name = " << person->getName(); // Get the person's name // The person object is now destroyed on exit } int main() { cout << endl << "Now calling doSomeMemoryWork()" << endl; doSomeMemoryWork(); cout << "Now calling getPersonDetails()" << endl; getPersonDetails(); return 0; }
Listing 5 calls two functions:
doSomeMemoryWork();
and
getPersonDetails();
The first function (doSomeMemoryWork) makes some C calls to malloc(), memset(), and free(). This function also does a little bit of pointer reassignment and prints the results.
Inside getPersonDetails(), I use a unique_ptr to create an object that then gets deleted automatically.
Not much happens inside the C++ code. However, there's no real limit to the complexity that can be added to the invoked C++ program. In other words, any legacy C++ program can be run in this way. As with all software, the better the code quality, the better the experience!