Skip to main content
gamedev.net
🔒 Locked

Python doesn't like me

Started by jperalta Apr 28, 2004 at 8:24 PM 10 replies 900+ views
Original Post
jperalta
jperalta
Ok, so... I''m 99% sure the problem isn''t the string marshalling now. It seems that Python doesn''t particularly like me or how I''m interfacing with it. I made some adjustements and I now have the following code:
void ScriptHost::Run(System::String *filename, System::String *function,int argc,System::String *args[]) {
	Py_Initialize();
	PyObject *pName, *pModule, *pDict, *pFunc;
	PyObject *pArgs, *pValue;
	char* fName = (char*)(Marshal::StringToHGlobalAnsi(filename).ToPointer());
	System::Console::Out->Write("Contents of fName: ");
	System::Console::Out->WriteLine(fName);
	pName = PyString_FromString(fName);
	pModule = PyImport_Import(pName);
	Py_DECREF(pName);

	if (pModule != NULL) {
		pDict = PyModule_GetDict(pModule);
		pFunc = PyDict_GetItemString(pDict,(char*)Marshal::StringToHGlobalAnsi(function).ToPointer());
		if (pFunc && PyCallable_Check(pFunc)) {
			pArgs = PyTuple_New(argc);
			for (int i = 0; i < argc; ++i) {
				pValue = PyInt_FromLong(Convert::ToInt32(args[i]));
				if (!pValue) {
					Py_DECREF(pArgs);
					Py_DECREF(pModule);
					Console::Error->WriteLine("Cannot convert argument");
					return;
				}
				/* pValue reference stolen here: */
				PyTuple_SetItem(pArgs, i, pValue);
			}
			pValue = PyObject_CallObject(pFunc, pArgs);
			Py_DECREF(pArgs);
			if (pValue != NULL) {
				System::Console::Out->WriteLine("Result of call: {0}",Convert::ToString(PyInt_AsLong(pValue)));
				Py_DECREF(pValue);
			}
			else {
				Py_DECREF(pModule);
				PyErr_Print();
				System::Console::Error->WriteLine("Call failed");
				return;
			}
			/* pDict and pFunc are borrowed and must not be Py_DECREF-ed */
		}
		else {
			if (PyErr_Occurred())
				PyErr_Print();
			Console::Error->WriteLine("Cannot find function \"{0}\"", function);
		}
		Py_DECREF(pModule);
	}
	else {
		PyErr_Print();
		Console::Error->WriteLine("Failed to load \"{0}\"\n", filename);
		return;
	}
	Py_Finalize();
	return;
}
And the output is: Contents of fName: test.py ImportError: No module named py Failed to load "test.py" Any help would be most appreciated.
Flarelocke
Flarelocke
You need to load it like
import test  
instead of
import test.py  


The .py on the latter makes Python think that your test module is a directory, and that py is a module in that directory (i.e. it thinks there's a test/py.py, test/py.pyc or test/py.pyd file)

[edit]Just realized that you do this in C, rather than in Python. So you need fName to be the base, rather than the base+extension.

[edited by - Flarelocke on April 28, 2004 10:17:25 PM]
---New infokeeps brain running;must gas up!
Gorg
Gorg
I think it is much cleaner to run the code from a string.


void ExecuteCode( const std::string& code )
{
int result = PyRun_SimpleString( const_cast<char*>(code.c_str()));
if ( result == -1 )
{
throw std::runtime_error( std::string( "Python : Error running code : " ) + code );
}
}


ExecuteCode( "import module\nmodule.func( arg1, arg2)" )



All you need to do is construct the string.

Of course, if you want the content of the return value, it is easier by directly calling the C api.

[edited by - Gorg on April 28, 2004 10:46:36 PM]

[edited by - Gorg on April 28, 2004 10:47:05 PM]
jperalta
jperalta
quote:
Original post by Flarelocke
...
Just realized that you do this in C, rather than in Python. So you need fName to be the base, rather than the base+extension.
...



I passed it in "test" instead of "test.py" and the new result was:

Contents of fName: test
Cannot find function "multiply"

The source for my python file is:

def multiply(a,b):
print "Will compute", a, "times", b
c = 0
for i in range(0, a):
c = c + b
return c




Flarelocke
Flarelocke
Try test.multiply rather than just multiply?
---New infokeeps brain running;must gas up!
jperalta
jperalta
quote:
Original post by Flarelocke
Try test.multiply rather than just multiply?


Still no dice. I really think Python hates me.
Flarelocke
Flarelocke
Can you try to make a simplified test cast? i.e. substitute values in for these arguments, remove some of the extra lines, etc.
---New infokeeps brain running;must gas up!
jperalta
jperalta
@AP- No, it hates me.

@Flare-
Ok, so, here''s the minimal source:


void ScriptHost::Run() {
Py_Initialize();
PyObject *pName, *pModule, *pDict, *pFunc;

pName = PyString_FromString("test");
pModule = PyImport_Import(pName);
Py_DECREF(pName);

if (pModule != NULL) {
pDict = PyModule_GetDict(pModule);
pFunc = PyDict_GetItemString(pDict,"multiply");
if (pFunc == NULL) {
Console::Out->WriteLine("pFunc is null.");
return;
}
else if (!PyCallable_Check(pFunc)) {
Console::Out->WriteLine("Function not callable");
return;
}
else {
System::Console::Out->WriteLine("pFunc not null and function callable.");
return;
}
}
else {
PyErr_Print();
Console::Out->WriteLine("Could not find module.");
return;
}
Py_Finalize();
return;
}


Result is: "pFunc is null." I have no idea what that means is wrong. The Python/C API isn''t very well documented.
jperalta
jperalta
Victory is mine. Ok, it appears that Python comes with a test module built in, so I renamed my module and put it in the proper place and voila. Thanks for all your help Flarelocke.
Flarelocke
Flarelocke
It was my pleasure.
---New infokeeps brain running;must gas up!

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.