Ok, I finally did it, and as I expected, once it's done it looks easy to do.
What is not easy is to gather a huge tone on information split a bit everywhere, so I'm going to write this mini-tutorial to help anyone who will be in my case in the future.
GOAL:
====
You already have a full working game engine done in C/C++, and you want to extend it by using Python as a scripting language to modify some game states, entity states, etc..., by sending pointer of your structure states to Python.
I assume you're already a bit familiar with Python (version used = 2.5.2).
ie: at least, u know this => http://www.poromenos.org/tutorials/python?
I'm using Swig v1.3.36 to wrap my C stuff to be used in Python : http://www.swig.org/ .
It seems to be the most easy one to use, although the doc & the beginner guide is really repelling at 1st... :-S (especially, there's not a word about how it works when embedding Python; all examples are done by extending it)
You have to create an interface file, that Swig will parse to create a .c wrap file that you'll have to insert into your project.
For our case, we'll include this .c wrap file directly into our main code.
Here the interface file "MyProject.i" for Swig :
Code:
%module MyProject // Name of your project
%inline %{ // the inline keyword allows to have only 1 declaration, both used by Swig, and then copied as it to the .c wrap file
extern int MyPrint(char *Str); // to easily get some text from Python
extern int PythonError(PyObject *pObj); // To catch Python Error ; although, MyPrint could be used instead, it'd work in the same way
struct SPythoned // Our test structure
{
float x, y, z;
int Stat[32];
char *pName, ShortName[32];
};
%}
You create the wrap .c file using this command :
Swig -python MyProject.i
You can add the file "MyProject.i" to your Visual Studio project, and do this custom step build :
[PathToSwig]\Swig.exe -python "$(InputPath)"
Output = $(InputName)_wrap.c
Now, you have MyProject_wrap.c .
Here the Python script file "PyTest.py" to test the function & structure ; in it we define the Python function TestObject that receives an object which is a pointer to an instance of our C structure SPythoned :
Code:
import MyProject
def TestObject(o):
MyProject.MyPrint(o.pName + "\n")
MyProject.MyPrint(o.ShortName) # + String doesn't work with ShortName
MyProject.MyPrint("\n")
o.ShortName = "yaataa!!"
o.x = 1
o.y = o.x * 2.5
o.z = o.x + o.y
But we will also need to redirect the Python error output, coz PyErr_Print() uses it, and there's no other way to get this output (it seems that Python developers "forgot" to add a PyErr_PrintToBuffer(char *Buffer) or something like this... :-S ).
Here the Python script "Error.Py" to do the redirection :
Code:
import MyProject, sys
class Redirect:
def write(self, s):
MyProject.PythonError(s)
def Redirection():
sys.stderr = sys.stdout = Redirect()
And here the C++ code, to test all of this :
Code:
#include <stdio.h>
#include <Python.h>
extern "C" // only needed when compiling in C++
{
#include "MyProject_wrap.c"
}
// struct SPythoned is defined within MyProject_wrap.c just included above
extern "C" int MyPrint(char *Str)
{
return printf(Str);
}
extern "C" int PythonError(PyObject *pObj)
{
char *Str = PyString_AsString(pObj);
return printf(Str);
}
void CheckPythonError(void)
{
if (PyErr_Occurred() != NULL)
{
PyErr_Print();
PyErr_Clear();
}
}
void PythonTest(void)
{
freopen("PyTest.Log", "w", stdout); // Redirect output, so our printf() will go into "PyTest.Log"
Py_Initialize(); // Init Python
SWIG_init(); // Initialise SWIG types
init_MyProject(); // Init our project wrapped by Swig
//=== Redirect Python error output
int Ok = PyRun_SimpleString("import Error\n"
"Error.Redirection()\n");
//=== Do a little test
PyRun_SimpleString("import MyProject\n"
"from time import time,ctime\n"
"Str = 'Today is ' + ctime(time()) + '\\n'\n"
"MyProject.MyPrint(Str)\n");
CheckPythonError();
//=== Test our structure
SPythoned Object;
PyObject *pMod, *pGlobalDict, *pFunc, *pResult, *pArg;
Object.pName = "Toto";
strcpy(Object.ShortName, "T.");
pMod = PyImport_ImportModule("PyTest"); // Load "PyTest.py" (it will create a compiled version "PyTest.pyc")
if (pMod)
{
pGlobalDict = PyModule_GetDict(pMod); // Get main dictionary
if (pGlobalDict)
{
pFunc = PyDict_GetItemString(pGlobalDict, "TestObject"); // Look for function TestObject
if (pFunc)
{
pArg = SWIG_NewPointerObj((void*)&Object, SWIGTYPE_p_SPythoned, 1); // Get Python Object for our Structure Pointer
if (pArg)
{
pResult = PyObject_CallFunction(pFunc, "O", pArg);
CheckPythonError();
Py_CLEAR(pResult);
printf("x = %g; y = %g; z = %g; Name = %s / %s\n",
Object.x, Object.y, Object.z,
Object.pName, Object.ShortName);
}
}
}
}
Py_Finalize();
}
That's all ! 
You can do the same with C++ classes, and with structures within structures. Swig can parse & wrap most C/C++ declarations.
Note: To build your project in debug mode, you'll need python25_d.lib & python25_d.dll . To get these files, you must download the Python sources, and build the PCBuild in debug. For me, it failed using VS2005EE, but worked with VS2008.
I hope this mini-tutorial will help..!