Some help reverse engennering a piece of code?
Moderator: ScummVM Team
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
This i think i understand
It prints the error if the output of the function is zero (ironically, it actually doesn't print anything if there is no error, so it might be a good idea to return 0 unconditionally to avoid the problem area).
And basically i don't understand this part of the assembly.
So there was no error, and so the code decreases the ... value pointed by the return? And if it is zero it flushes the line, if not it calls a unknown function with pointer after the pointer in the return?
I can't really attach the dbg to the running game to see where the call nds up. The game has a anti-debuger.
It prints the error if the output of the function is zero (ironically, it actually doesn't print anything if there is no error, so it might be a good idea to return 0 unconditionally to avoid the problem area).
Code: Select all
200DAB45 |. FF15 90331720 CALL DWORD PTR DS:[<&vampire_python21.PyRun_ConsoleString>]
200DAB4B |. 83C4 14 ADD ESP,14
200DAB4E |. 85C0 TEST EAX,EAX
200DAB50 |. 75 08 JNE SHORT 200DAB5A
200DAB52 |. FF15 94331720 CALL DWORD PTR DS:[<&vampire_python21.PyErr_Print>]
200DAB58 |.- EB 1E JMP SHORT <JMP.&vampire_python21.Py_FlushConsoleOutput> ; Jump to vampire_python21.Py_FlushConsoleOutput
And basically i don't understand this part of the assembly.
So there was no error, and so the code decreases the ... value pointed by the return? And if it is zero it flushes the line, if not it calls a unknown function with pointer after the pointer in the return?
Code: Select all
200DAB5A |> FF08 DEC DWORD PTR DS:[EAX]
200DAB5C |. 75 0A JNE SHORT 200DAB68
200DAB5E |. 8B48 04 MOV ECX,DWORD PTR DS:[EAX+4]
200DAB61 |. 50 PUSH EAX
200DAB62 |. FF51 18 CALL DWORD PTR DS:[ECX+18]
200DAB65 |. 83C4 04 ADD ESP,4
200DAB68 |> FF15 98331720 CALL DWORD PTR DS:[<&vampire_python21.Py_FlushLine>]
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
Dunno. It looks to me that the code path that crashes is the success path (returning a valid pointer). Maybe it is just the print i'm doing in the replacement bellow? Damn anti debuggers.
The original functions redirected the python stdout and stderr to the console too, so maybe that is all related to that.
Anyway, the console works more or less, modulo that uncertainty and printing to stdout.
Another problem is there are other (default) functions that are failing on map load, including what appears to be a bog standard import a directory (the others are related to modules i didn't bother to compile and include yet).
The original functions redirected the python stdout and stderr to the console too, so maybe that is all related to that.
Code: Select all
PyAPI_FUNC(int) PyRun_ConsoleString(const char *, int, PyObject*, PyObject*);
int PyRun_ConsoleString(const char *str, int typeOfExpression, PyObject* globals, PyObject* locals){
PyObject * code;
//read this
//http://docs.python.org/c-api/veryhigh.html#Py_eval_input
//typeOfExpression is always equal to 256 or Py_single_input.
//So the input for the console is a series of statements, not expressions. BUT
//one of the primitive python statements is the expression_stmt:
//http://docs.python.org/reference/simple_stmts.html#grammar-token-expression_stmt
//that indeed evaluates expressions like 1+2 so this can be used for exec and output
assert(typeOfExpression == Py_single_input);
code = PyRun_String(str, typeOfExpression, globals, locals);
if(code){
//print the console evaluation result to std out TODO: filter "None"
PyObject_Print(code, stdout, NULL);
printf("\r\n");
Py_DECREF(code);
code = NULL;
//the original dll probably returned a pointer to something
//It checks against NULL (0) and prints the error if it occurred, to stdout
//if it is not null, it does something different that would need a running
//dbg to find out (bloodlines has anti dbg proctetion, and i dont know how
//work around that)
}
return 0;
}
Another problem is there are other (default) functions that are failing on map load, including what appears to be a bog standard import a directory (the others are related to modules i didn't bother to compile and include yet).
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
Did a little "printf tracing"
This is ok
This is expected
Again ok.
Ok
Not compiled yet modules, ok
What? (santamonica is a dir in vampire\python\santamonica with a python file loaded during map load.) How can't it import it considering that it appended vampire\python\santamonica to the sys.path on the first lines? And what is that weird attribute error?
Note: i'm using wine. The game runs fine on it.
Code: Select all
Called simple string: import sys; sys.path.append("Z:\\home\\paulo\\OS Images\\shared\\Vampire the Masquerade - Bloodlines\\Vampire the Masquerade - Bloodlines\\vampire\python")
Code: Select all
sys:1: RuntimeWarning: Python C API version mismatch for module vampire: This Python has API version 1013, module vampire has version 1010.
Code: Select all
Called simple string: sys.path.append("Z:/home/paulo/OS Images/shared/Vampire the Masquerade - Bloodlines/Vampire the Masquerade - Bloodlines/vampire/python/lib/")
Code: Select all
Called simple string: import __main__
Called simple string: from vampire import *
Code: Select all
Called simple string: from vamputil import *
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "Z:\home\paulo\OS Images\shared\Vampire the Masquerade - Bloodlines\Vampire the Masquerade - Bloodlines\vampire\python\vamputil.py", line 6, in <module>
from zvtool.zvtool import *
File "Z:\home\paulo\OS Images\shared\Vampire the Masquerade - Bloodlines\Vampire the Masquerade - Bloodlines\vampire\python\zvtool\zvtool.py", line 12, in <module>
from zvtool_file import *
File "Z:\home\paulo\OS Images\shared\Vampire the Masquerade - Bloodlines\Vampire the Masquerade - Bloodlines\vampire\python\zvtool\zvtool_file.py", line 9, in <module>
from struct import *
ImportError: No module named struct
Code: Select all
Called simple string: sys.path.append("Z:/home/paulo/OS Images/shared/Vampire the Masquerade - Bloodlines/Vampire the Masquerade - Bloodlines/vampire/python/santamonica")
AttributeError: 'module' object has no attribute '_extension_registry'
Called simple string: from santamonica import *
Traceback (most recent call last):
File "<string>", line 1, in <module>
ImportError: No module named santamonica
Note: i'm using wine. The game runs fine on it.
Last edited by Serious Callers Only on Sun Mar 06, 2011 9:06 pm, edited 3 times in total.
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
Mmmm. Interesting. That santamonica error is a missing
"__init__.py" (empty) file on the directory.
It appears that to be recognized as a package they must have that file.
Also, i wasn't printing if the command was successful or not (stupidly). Of those above, the only successful import statements were __main__ and from vampire import * were successful. All others failed because of not having __init__.py.
What the game is trying and failing to do:
Putting the __init__.py just makes the later
work, when it should if that first call worked. But the question is, why is it failing.
sys.path is a list!
"__init__.py" (empty) file on the directory.
It appears that to be recognized as a package they must have that file.
Also, i wasn't printing if the command was successful or not (stupidly). Of those above, the only successful import statements were __main__ and from vampire import * were successful. All others failed because of not having __init__.py.
What the game is trying and failing to do:
Code: Select all
AttributeError: 'module' object has no attribute '_extension_registry'
Failed, Called simple string: sys.path.append("Z:/home/paulo/OS Images/shared/Vampire the Masquerade - Bloodlines/Vampire the Masquerade - Bloodlines/vampire/python/santamonica")
Code: Select all
Success, Called simple string: from santamonica import *
sys.path is a list!
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
This is some seriously broken compiler design. That error doesn't appear to have anything to do with the sys.
It is a simple symptom of a earlier error that was not "cleared". In the middle of the compiler, before compiling the new code, there is a call checking : "Oh, there is a exception, better bail out".
There is no such check at the interface borders.
A_call_from_the_foreign_function_interface_can_make_a_posterior_call_fail
They (cpython guys) probably expected people to clear the exception after calling the code. (but, by god, they could have failed fast and tell a meaningful exception instead of misleading dross).
But troika probably put it IN the functions calls).
(i didn't edit the functions that have that error).
It is a simple symptom of a earlier error that was not "cleared". In the middle of the compiler, before compiling the new code, there is a call checking : "Oh, there is a exception, better bail out".
There is no such check at the interface borders.
A_call_from_the_foreign_function_interface_can_make_a_posterior_call_fail
They (cpython guys) probably expected people to clear the exception after calling the code. (but, by god, they could have failed fast and tell a meaningful exception instead of misleading dross).
But troika probably put it IN the functions calls).
(i didn't edit the functions that have that error).
Last edited by Serious Callers Only on Mon Mar 07, 2011 3:33 am, edited 1 time in total.
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
Which reminds me, a better design would be to wrap the dll and only export the functions used directly (and the additional code for they to work the "Troika way").
So i could just replace python by drag&drop if a new minor 2.7 version comes out (or i want more modules whatever).
Is this easy to do in c? Not exactly my sharpest tool as you can see.
There is one problem:
I had to add the header in this function before Bloodlines accepted the compiled dll.
I don't really understand what that is calling. I tried to "go to definition/declaration in VS2003 and it says it can't find it. It isn't in the file either. Is this some kind of proprocessor shenanigans?
So i could just replace python by drag&drop if a new minor 2.7 version comes out (or i want more modules whatever).
Is this easy to do in c? Not exactly my sharpest tool as you can see.
There is one problem:
Code: Select all
/* for binary compatibility with 2.2 */
#undef _PyObject_Del
PyAPI_FUNC(void) _PyObject_Del(PyObject *);
void
_PyObject_Del(PyObject *op)
{
PyObject_FREE(op);
}
I don't really understand what that is calling. I tried to "go to definition/declaration in VS2003 and it says it can't find it. It isn't in the file either. Is this some kind of proprocessor shenanigans?
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
Trying to wrap the dll dynamically with LoadLibrary didn't work somehow.
I was getting along inserting the functions (inserted 4 as you can see and had the list of the others, when:
I was getting along inserting the functions (inserted 4 as you can see and had the list of the others, when:
Bizarre. I guess it's back to compiling python.Unhandled page fault on read access to 0x00000000 at address (nil) (thread 002b), starting debugger...
Unhandled exception: page fault on read access to 0x00000000 in 32-bit code (0x00000000).
Code: Select all
#include <windows.h>
#include <stdio.h>
#include "Python.h"
extern "C" {
HMODULE pythonLib;
//python functions the original game uses/modifies, dynamically import them
PyObject* (*py_runstring) (const char*, int, PyObject*, PyObject*);
int (*py_runsimpleString) (const char*);
void (*py_pyObjectDel) (PyObject*);
void (*py_setProgramName) (char *);
//GetProcAddresses
//Argument1: hLibrary - Handle for the Library Loaded
//Argument2: lpszLibrary - Library to Load
//Argument3: nCount - Number of functions to load
//[Arguments Format]
//Argument4: Function Address - Function address we want to store
//Argument5: Function Name - Name of the function we want
//[Repeat Format]
//
//Returns: FALSE if failure
//Returns: TRUE if successful
BOOL GetProcAddresses( HMODULE *hLibrary,
LPCSTR lpszLibrary, INT nCount, ... )
{
va_list va;
va_start( va, nCount );
if ( ( *hLibrary = LoadLibrary( lpszLibrary ) )
!= NULL )
{
FARPROC * lpfProcFunction = NULL;
LPSTR lpszFuncName = NULL;
INT nIdxCount = 0;
while ( nIdxCount < nCount )
{
lpfProcFunction = va_arg( va, FARPROC* );
lpszFuncName = va_arg( va, LPSTR );
if ( ( *lpfProcFunction =
GetProcAddress( *hLibrary,
lpszFuncName ) ) == NULL )
{
lpfProcFunction = NULL;
return FALSE;
}
nIdxCount++;
}
}
else
{
va_end( va );
return FALSE;
}
va_end( va );
return TRUE;
}
int __declspec (dllexport) Initialize(){
BOOL success = GetProcAddresses(&pythonLib, "python.dll", 3,
&py_runstring, "PyRun_String",
&py_runsimpleString, "PyRun_SimpleString",
&py_setProgramName, "Py_SetProgramName",
&py_pyObjectDel, "_PyObject_Del" );
if(!success){
printf("Failed dynamically initializing python.dll in the vampire dir\r\n");
}
return success;
}
int __declspec (dllexport) Terminate(){
if(pythonLib != NULL){
FreeLibrary(pythonLib);
}
return TRUE;
}
void __declspec (dllexport) Py_SetGameInterface(void){
//TODO, enable extensions
//Py_NoSiteFlag = 1;
}
void __declspec (dllexport) Py_FlushConsoleOutput(void){
printf("\r\n");
return;
}
int __declspec (dllexport) PyRun_ConsoleString(const char *str, int typeOfExpression, PyObject* globals, PyObject* locals){
PyObject * code;
if (PyErr_Occurred()){
//if there is a error saved the compiler will bail out while compiling.
//this error can be bogus, simply because a previous error - on a previous
//execution was not cleared by thecaller.
//The cpython guys prefered to centralize the error checking to fail early.
//Probably they thought no one would change the api proper. Troikan comes along and
//decides to modify the api directly (for no reason at all)
//Troika probably cleared previous exceptions here on all calls they used.
//Either after or before, but i choose before, because there might be some caller
//checking too.
printf("Warning, previous call c code didnt clear the failing exception\r\n");
PyErr_Clear();
}
//read this
//http://docs.python.org/c-api/veryhigh.html#Py_eval_input
//typeOfExpression is always equal to 256 or Py_single_input.
//So the input for the console is a series of statements, not expressions. BUT
//one of the primitive python statements is the expression_stmt:
//http://docs.python.org/reference/simple_stmts.html#grammar-token-expression_stmt
//that indeed evaluates expressions like 1+2 so this can be used for exec and output
assert(typeOfExpression == Py_single_input);
code = py_runstring(str, typeOfExpression, globals, locals);
printf("%sCalled console string: %s\r\n", code ? "Success, " : "Failed, ", str);
if(code){
//TODO: this should be printing to the game console instead
//TODO: filter "None"
PyObject_Print(code, stdout, NULL);
Py_DECREF(code);
code = NULL;
//the original dll probably returned a pointer to something
//It checks against NULL (0) and prints the error if it occurred, to stdout
//if it is not null, it does something different that would need a running
//dbg to find out (bloodlines has anti dbg protection, and i dont know how
//work around that). Seems to work fine anyway?
}
return 0;
}
//Original python functions modified by troika
#undef PyRun_SimpleString
int __declspec (dllexport) PyRun_SimpleString(const char *st)
{
int result;
if (PyErr_Occurred()){
printf("Warning, previous call c code didnt clear the failing exception\r\n");
PyErr_Clear();
}
result = py_runsimpleString(st);
printf("%sCalled simple string: %s\r\n", result == 0 ? "Success, " : "Failed, ", st);
return result;
}
//this function was deprecated on python 2.3 check if it can still link
#undef _PyObject_Del
void __declspec (dllexport) _PyObject_Del(PyObject *op)
{
py_pyObjectDel(op);
}
//Original functions used unmodified by troika.
/**
#undef PyErr_Clear
void __declspec (dllexport) PyErr_Clear(){
}
#undef PyErr_Print
void __declspec (dllexport) PyErr_Print(){
}
#undef PyErr_SetString
void __declspec (dllexport) PyErr_SetString(){
}
#undef PyFloat_AsDouble
void __declspec (dllexport) PyFloat_AsDouble(){
}
#undef PyFloat_FromDouble
void __declspec (dllexport) PyFloat_FromDouble(){
}
#undef PyImport_AddModule
void __declspec (dllexport) PyImport_AddModule(){
}
#undef PyInt_AsLong
void __declspec (dllexport) PyInt_AsLong(){
}
#undef PyInt_FromLong
void __declspec (dllexport) PyInt_FromLong(){
}
#undef PyLong_AsDouble
void __declspec (dllexport) PyLong_AsDouble(){
}
#undef PyModule_AddObject
void __declspec (dllexport) PyModule_AddObject(){
}
#undef PyModule_GetDict
void __declspec (dllexport) PyModule_GetDict(){
}
#undef _PyObject_New
void __declspec (dllexport) _PyObject_New(){
}
#undef PyObject_Str
void __declspec (dllexport) PyObject_Str(){
}
#undef PyString_AsString
void __declspec (dllexport) PyString_AsString(){
}
#undef PyString_FromString
void __declspec (dllexport) PyString_FromString(){
}
#undef Py_Finalize
void __declspec (dllexport) Py_Finalize(){
}
#undef Py_FlushLine
void __declspec (dllexport) Py_FlushLine(){
}
#undef Py_Initialize
void __declspec (dllexport) Py_Initialize(){
}
**/
#undef Py_SetProgramName
void __declspec (dllexport) Py_SetProgramName(char * name){
py_setProgramName(name);
}
}
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
-
- Got a warning
- Posts: 173
- Joined: Thu Feb 25, 2010 7:44 am
This approach is kinda working, but VS is giving (rightfully i guess) this warning for each function redirected:
vampire_python21.cpp(207) : warning C4273: 'Py_Initialize' : inconsistent dll linkage
Any alternative or tips to solve the warning?
vampire_python21.cpp(207) : warning C4273: 'Py_Initialize' : inconsistent dll linkage
Any alternative or tips to solve the warning?
Code: Select all
#include "Python.h"
#include <windows.h>
#include <stdio.h>
HMODULE pythonLib;
//python functions the original game uses/modifies, dynamically import them
PyObject* (*py_runstring) (const char*, int, PyObject*, PyObject*);
PyObject* (*py__PyObjectNew) (PyTypeObject*);
int (*py_runsimpleString) (const char*);
void (*py_initialize) (void);
void (*py_setProgramName) (char*);
PyObject* (*py_pyImportAddModule)(const char *);
int (*py_moduleAddObject) (PyObject*, const char*, PyObject*);
PyObject* (*py_moduleGetDict) (PyObject*);
void (*py_errorPrint) (void);
PyObject* (*py_objectStr) (PyObject*);
char* (*py_stringAsString) (PyObject*);
PyObject* (*py_stringFromString) (const char*);
extern "C" {
//GetProcAddresses
//Argument1: hLibrary - Handle for the Library Loaded
//Argument2: lpszLibrary - Library to Load
//Argument3: nCount - Number of functions to load
//[Arguments Format]
//Argument4: Function Address - Function address we want to store
//Argument5: Function Name - Name of the function we want
//[Repeat Format]
//
//Returns: FALSE if failure
//Returns: TRUE if successful
__declspec (dllexport) int GetProcAddresses( HMODULE *hLibrary,
LPCSTR lpszLibrary, INT nCount, ... )
{
va_list va;
va_start( va, nCount );
if ( ( *hLibrary = LoadLibrary( lpszLibrary ) )
!= NULL )
{
FARPROC * lpfProcFunction = NULL;
LPSTR lpszFuncName = NULL;
INT nIdxCount = 0;
while ( nIdxCount < nCount )
{
lpfProcFunction = va_arg( va, FARPROC* );
lpszFuncName = va_arg( va, LPSTR );
printf("%s\r\n",lpszFuncName);
if ( ( *lpfProcFunction =
GetProcAddress( *hLibrary,
lpszFuncName ) ) == NULL )
{
lpfProcFunction = NULL;
return FALSE;
}
nIdxCount++;
}
}
else
{
va_end( va );
return 0;
}
va_end( va );
return 1;
}
__declspec (dllexport) int APIENTRY DllMain(HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
int success;
char bufExePath[MAX_PATH + 1] = { 0 };
unsigned long nChars;
switch( ul_reason_for_call ) {
case DLL_PROCESS_ATTACH:
nChars = GetModuleFileName(NULL, bufExePath, MAX_PATH);
if(nChars <= 0){
printf("Failed getting the vampire dir\r\n");
return 0;
}
for( ; nChars > 0; nChars--){
//think windows accepts both
if(bufExePath[nChars]=='\\' || bufExePath[nChars]=='/'){
break;
}
}
if(nChars == 0){
printf("Failed getting the vampire dir\r\n");
return 0;
}
strcpy(&bufExePath[nChars+1],"Bin\\python.dll\0");
success = GetProcAddresses(&pythonLib, bufExePath,
9,
//&py_objectStr, "PyObject_Str",
//&py_stringAsString, "PyString_AsString",
//&py_stringFromString, "PyString_FromString",
&py_errorPrint, "PyErr_Print",
&py_moduleGetDict, "PyModule_GetDict",
&py_moduleAddObject, "PyModule_AddObject",
&py_initialize, "Py_Initialize",
&py__PyObjectNew, "_PyObject_New",
&py_runstring, "PyRun_String",
&py_runsimpleString, "PyRun_SimpleString",
&py_setProgramName, "Py_SetProgramName",
&py_pyImportAddModule, "PyImport_AddModule"
);
if(!success){
printf("Failed dynamically initializing python.dll on %s\r\n", bufExePath);
}
return success;
case DLL_PROCESS_DETACH:
if(pythonLib != NULL){
FreeLibrary(pythonLib);
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
default:
return 1;
}
}
//functions added by troika
__declspec (dllexport) void Py_SetGameInterface(void){
//TODO, enable extensions
Py_NoSiteFlag = 1;
}
__declspec (dllexport) void Py_FlushConsoleOutput(void){
printf("\r\n");
return;
}
__declspec (dllexport) int PyRun_ConsoleString(const char *str, int typeOfExpression, PyObject* globals, PyObject* locals){
PyObject * code;
if (PyErr_Occurred()){
//if there is a error saved the compiler will bail out while compiling.
//this error can be bogus, simply because a previous error - on a previous
//execution was not cleared by the caller.
//The cpython guys prefered to centralize the error checking to fail early.
//Probably they thought no one would change the api proper.
//Troika probably cleared previous exceptions here on all calls they used.
//Either after or before, but i choose before, because there might be some caller
//checking too.
printf("Warning, previous call c code didnt clear the failing exception\r\n");
PyErr_Clear();
}
//read this
//http://docs.python.org/c-api/veryhigh.html#Py_eval_input
//typeOfExpression is always equal to 256 or Py_single_input.
//So the input for the console is a series of statements, not expressions. BUT
//one of the primitive python statements is the expression_stmt:
//http://docs.python.org/reference/simple_stmts.html#grammar-token-expression_stmt
//that indeed evaluates expressions like 1+2 so this can be used for exec and output
assert(typeOfExpression == Py_single_input);
code = py_runstring(str, typeOfExpression, globals, locals);
printf("%sCalled console string: %s\r\n", code ? "Success, " : "Failed, ", str);
if(code){
//TODO: this should be printing to the game console instead
//TODO: filter "None"
PyObject_Print(code, stdout, NULL);
Py_DECREF(code);
code = NULL;
//the original dll probably returned a pointer to something
//It checks against NULL (0) and prints the error if it occurred, to stdout
//if it is not null, it does something different that would need a running
//dbg to find out (bloodlines has anti dbg protection, and i dont know how
//work around that). Seems to work fine anyway?
}
return 0;
}
//Original python functions used/modified by troika
#undef PyRun_SimpleString
__declspec (dllexport) int PyRun_SimpleString(const char *st)
{
int result;
if (PyErr_Occurred()){
printf("Warning, previous call c code didnt clear the failing exception\r\n");
PyErr_Clear();
}
result = py_runsimpleString(st);
printf("%sCalled simple string: %s\r\n", result == 0 ? "Success, " : "Failed, ", st);
return result;
}
//Original functions used unmodified by troika.
#undef Py_Initialize
__declspec (dllexport) void Py_Initialize(void){
py_initialize();
}
//this function was deprecated on python 2.3 check if this works with TRACEREFS
#undef _PyObject_Del
__declspec (dllexport) void _PyObject_Del(PyObject *op)
{
Py_DECREF(op);
}
#undef _PyObject_New
__declspec (dllexport) PyObject* _PyObject_New(PyTypeObject *type){
return py__PyObjectNew(type);
}
#undef PyImport_AddModule
__declspec (dllexport) PyObject* PyImport_AddModule(const char *name){
return py_pyImportAddModule(name);
}
#undef PyModule_AddObject
__declspec (dllexport) int PyModule_AddObject(PyObject *module, const char *name, PyObject *value){
return py_moduleAddObject(module,name,value);
}
#undef PyModule_GetDict
__declspec (dllexport) PyObject* PyModule_GetDict(PyObject * module){
return py_moduleGetDict(module);
}
#undef PyErr_Print
__declspec (dllexport) void PyErr_Print(){
py_errorPrint();
}
//#undef PyObject_Str
//PyObject * __declspec (dllexport) PyObject_Str(PyObject *o){
// return py_objectStr(o);
//}
//#undef PyString_AsString
//char* __declspec (dllexport) PyString_AsString(PyObject * o){
// return py_stringAsString(o);
//}
//#undef PyString_FromString
//PyObject* __declspec (dllexport) PyString_FromString(const char * s){
// return py_stringFromString(s);
//}
/**
#undef PyErr_Clear
void __declspec (dllexport) PyErr_Clear(){
}
#undef PyErr_SetString
void __declspec (dllexport) PyErr_SetString(){
}
#undef PyFloat_AsDouble
void __declspec (dllexport) PyFloat_AsDouble(){
}
#undef PyFloat_FromDouble
void __declspec (dllexport) PyFloat_FromDouble(){
}
#undef PyInt_AsLong
void __declspec (dllexport) PyInt_AsLong(){
}
#undef PyInt_FromLong
void __declspec (dllexport) PyInt_FromLong(){
}
#undef PyLong_AsDouble
void __declspec (dllexport) PyLong_AsDouble(){
}
#undef Py_Finalize
void __declspec (dllexport) Py_Finalize(){
}
#undef Py_FlushLine
void __declspec (dllexport) Py_FlushLine(){
}
**/
#undef Py_SetProgramName
__declspec (dllexport) void Py_SetProgramName(char * name){
py_setProgramName(name);
}
}