Calling a CyEngine function from the SDK

Afforess

The White Wizard
Joined
Jul 31, 2007
Messages
12,239
Location
Austin, Texas
I need to call CyEngine.AddSign(...) from the SDK, except it isn't exposed to us. I've tried simply exposing the function through BUG in BugCore.xml by:
Code:
<export module="EventSigns" function="addSign" to="CvAppInterface"/>

Except that calling via the SDK by this has no effect:
Code:
							CyArgsList argsList;
							argsList.add(this); //CvPlot*
							argsList.add(iJ); //PlayerType
							argsList.add(getLandmarkMessage()); //CvWString
							gDLL->getPythonIFace()->callFunction(PYCivModule, "addSign", argsList.makeFunctionArgs());

The code simply never executes. The lines before and after do.

I then moved to creating my own Entrypoint, Signs.py that had only this code:

Code:
from CvPythonExtensions import *
import CvUtil
			
gc = CyGlobalContext()	

localText = CyTranslator()

class Signs:

	def AddSign(self, argsList):
		CyEngine().addSign(argsList[0], argsList[1], argsList[2])

And called that from the SDK instead, but never worked either.

Does anyone know how to call this function from the SDK and what I am doing wrong?

PS. Firaxis, if you are listening, please when you expose your EXE functions, expose anything in python to the SDK, and vice-versa. Thanks!
 
I have not tried this, but here is what I think happens. Look at entrypoints/cvgameinterface.py. The functions there are not in any class. Suppose there is a call like
Code:
gDLL->getPythonIFace()->callFunction(PYGameModule, "somefunc", argsList.makeFunctionArgs());
We can see in cvdefines.h that PYGameModule is a string, "CvGameInterface". So this must instruct python to find the file CvGameInterface.py, look inside it for "def somefunc", and call that. Notice there is no class here. The entrypoints files do not have functions defined in classes, they are at the top level.

One thing you could try is to add a function directly into CvGameInterface.py, like:
Code:
def AddSign(self, argsList):
	CyEngine().addSign(argsList[0], argsList[1], argsList[2])
And then
Code:
gDLL->getPythonIFace()->callFunction(PYGameModule, "AddSign", argsList.makeFunctionArgs());
It would be neater to call from sdk code, into the inside of a class. I am sure that is possible but nothing in the entrypoints code from firaxis does this. So, to match their style, you could either put stuff into the top level of CvGameInterface, or add a similar file and put your function at the top level.
 
No dice. I don't have CvGameInterface in my mod, so I used CvAppInterface, but the same Idea. I added this, outside of the class:

Code:
def AddSign(argsList):
	CyEngine().addSign(argsList[0], argsList[1], argsList[2])

And called it with this:
Code:
							CyArgsList argsList;
							argsList.add(this);
							argsList.add(iJ);
							argsList.add(getLandmarkMessage().);
							gDLL->getPythonIFace()->callFunction(PYCivModule, "AddSign", argsList.makeFunctionArgs());
I even tried changing getLandmarkMessage() to getLandmarkMessage.GetCString(), but to no avail. Either something is wrong with my arguments, or I'm not calling it correctly. I can't tell which...
 
Let's try something a little simpler to prove that the call is even being made. Instead of trying to do something useful in the python routine, just print something to a logfile. Don't pass any arguments in you line with callFunction. Since there are many other lines, written by firaxis devs, which call functions in cvappinterface, you should be able to compare yours with some working examples. There must be some difference.

Once you are able to actually see the python routine running, then add some print statements which test whether the arguments are being passed usefully.
 
Added a print statement, the function is being called. Just with wrong arguments apparently.
 
I am not sure where you are adding your code in sdk. Is it in Cysomething.cpp or Cvsomething.cpp? In the firaxis code, I see a lot of:
Code:
[COLOR="Red"]CyPlot* pyPlot = new CyPlot(pDestPlot);[/COLOR]CyArgsList argsList;
argsList.add(gDLL->getPythonIFace()->[COLOR="red"]makePythonObject(pyPlot)[/COLOR]);	// pass in Plot class
long lResult=0;
gDLL->getPythonIFace()->callFunction(PYGameModule, "doCombat", argsList.makeFunctionArgs(), &lResult);
In you call code in the OP, is your "this" a CvPlot (wrong) or a CyPlot?

I may not always understand the firaxis code, but I try to slavishly copy the style.
 
A CvPlot. I switched over to a CyPlot using your example. Unfortuantly, while looking at other examples, I agree cyPlot is correct, but it didn't fix my problem. I have narrowed my problem down though. The playertype (int) argument is passed correctly, and so is the Message (string). So it's the plot that is giving me issues...
 
The CyPlot seems to be working correctly too. The only remaining factor is the CyEngine call now...
 
I got it to work, thank you for your help DavidAllen.

EF will be on a moment, demanding I post the solution. I'm sure of it.
 
Hey, could you please post what you had to do to get it to work? :rolleyes:

BTW, adding a new EntryPoints module will only work in a mod. The DLL will not be able to see it in CustomAssets unless you also place it (even empty) in the core Assets folder. I originally wanted to put all the extra BUG functions into a BugInterface module, but no dice.
 
Back
Top Bottom