Modder's Documentation

Could they be being used by Python. For the UI and mods.
Python bindings go the other way, they use boost:: python to export functions. They don't use this dllexport and dllimport interface. This interface is presumably used by only the exe.

Also, AdvCiv 0.95 cleaned this up and works properly.


Edit: Quote from AND forum, 2015:
Q4:
Why some "CvGlobals" methods are prefixed with DLLExport ? What does that do in the code?
DllExport makes the function accessible to the game exe. Don't change number of arguments if the function is exported (you can't tell the exe how to call) and don't export your own functions as the exe will never call them anyway.

Our mod has 2 functions, either incompatible or non-exported, to the import table of the exe.
 
Last edited:
It seems at the revision 391 of AND repository (2010-09-19), @Afforess removed DllExport from CvGame:: setAIAutoPlay.

@Thunderbrd added two booleans (bAssissinate, bClearCache) to CvPlot::getBestDefender at revisions 8395 (2015-12-13) and 9972 (2018-03-12), respectively.
I am not saying you were wrong adding new functionality to this function. But we can take advantage of function overloading, to keep one copy of CvPlot::getBestDefender that is DllExport'ed, in the original signature.
It looks like this:
Code:
DllExport CvUnit* getBestDefender(PlayerTypes eOwner, PlayerTypes eAttackingPlayer = NO_PLAYER, const CvUnit* pAttacker = NULL, bool bTestAtWar = false, bool bTestPotentialEnemy = false, bool bTestCanMove = false) const;
CvUnit* getBestDefender(PlayerTypes eOwner, PlayerTypes eAttackingPlayer = NO_PLAYER, const CvUnit* pAttacker = NULL, bool bTestAtWar = false, bool bTestPotentialEnemy = false, bool bTestCanMove = false, bool bAssassinate = false, bool bClearCache = false) const;        // Exposed to Python
Second line is our current code. First line is for compatibility. Some adjustments are needed to the flow of the function too.


In the other case, setAIAutoPlay, the original function has this signature:
Code:
DllExport void setAIAutoPlay(int iNewValue);
Our inherited function from AND has a different signature, which is
Code:
void setAIAutoPlay(PlayerTypes iPlayer, int iNewValue, bool bForced = false);
(Note this line doesn't need DllExport; a function with this signature is never imported by the exe.)
We can also utilize function overloading to provide the original one, alongside our current one, for compatibility.
 
Last edited:
It seems at the revision 391 of AND repository (2010-09-19), @Afforess removed DllExport from CvGame:: setAIAutoPlay.

@Thunderbrd added two booleans (bAssissinate, bClearCache) to CvPlot::getBestDefender at revisions 8395 (2015-12-13) and 9972 (2018-03-12), respectively.
I am not saying you were wrong adding new functionality to this function. But we can take advantage of function overloading, to keep one copy of CvPlot::getBestDefender that is DllExport'ed, in the original signature.
It looks like this:
Code:
DllExport CvUnit* getBestDefender(PlayerTypes eOwner, PlayerTypes eAttackingPlayer = NO_PLAYER, const CvUnit* pAttacker = NULL, bool bTestAtWar = false, bool bTestPotentialEnemy = false, bool bTestCanMove = false) const;
CvUnit* getBestDefender(PlayerTypes eOwner, PlayerTypes eAttackingPlayer = NO_PLAYER, const CvUnit* pAttacker = NULL, bool bTestAtWar = false, bool bTestPotentialEnemy = false, bool bTestCanMove = false, bool bAssassinate = false, bool bClearCache = false) const;        // Exposed to Python
Second line is our current code. First line is for compatibility. Some adjustments are needed to the flow of the function too.


In the other case, setAIAutoPlay, the original function has this signature:
Code:
DllExport void setAIAutoPlay(int iNewValue);
Our inherited function from AND has a different signature, which is
Code:
void setAIAutoPlay(PlayerTypes iPlayer, int iNewValue, bool bForced = false);
(Note this line doesn't need DllExport; a function with this signature is never imported by the exe.)
We can also utilize function overloading to provide the original one, alongside our current one, for compatibility.
Yeah I had no idea that it was originally a DllExport function or I would've been more reluctant to use additional parameters. I'm curious how we've managed to have this not create a problem all this time. Perhaps it may help to explain why there is such a huge delay with getBestDefender that doesn't seem explainable just by the processing within it at times. I would also be very concerned of potential bugs that may be caused if the EXE thinks one thing is happening when the dll goes another way due to having a mock function for 'compatibility'. So I have to wonder if the original issues that demanded another parameter could be solved another way. I'm really curious what problems we could expect this situation to be causing.
 
Some food for thought: https://www.evanmiller.org/type-punning-functions-in-c.html

It talks about how the machine handles calling in modern CPUs. I have not understood CPU architecture and instruction sets fully but this article may help.

I would also be very concerned of potential bugs that may be caused if the EXE thinks one thing is happening when the dll goes another way due to having a mock function for 'compatibility'. So I have to wonder if the original issues that demanded another parameter could be solved another way. I'm really curious what problems we could expect this situation to be causing.
Some behaviors are hard-coded in the exe; we can at best guess from its dependencies how they are processed, and based on our assumptions write dll code that does not interfere.

Just assume the exe doesn't know about additional parameters, and use unmodded code.
Caller in the dll: calls the improved function.
Caller in the exe: calls the original function, and ignore any additional argument the mod variant takes (use their default when it comes to logic switches that rely on these arguments)

There's no way to set up additional context for the caller in the exe that I can think of. New behaviors of the mod must be confined to the core dll.

However, it's safe to refer to global context from the original functions, so we may try to convert the additional arguments to be somewhat global, like we can to the force-overwrite flag, if we ensure they always represent the correct object when looked up. I'm talking so abstract here 'cause I've not examined the two functions in question yet...
 
Last edited:
However, it's safe to refer to global context from the original functions, so we may try to convert the additional arguments to be somewhat global, like we can to the force-overwrite flag, if we ensure they always represent the correct object when looked up. I'm talking so abstract here 'cause I've not examined the two functions in question yet...
Actually I do understand that. I did something similar with some steps in size matters but not for these reasons. Save a variable elsewhere then call that variable in the function rather than sending it as a parameter. That could be done here I think.
 
  • Like
Reactions: Anq
@Thunderbrd added two booleans (bAssissinate, bClearCache) to CvPlot::getBestDefender at revisions 8395 (2015-12-13) and 9972 (2018-03-12), respectively.
I am not saying you were wrong adding new functionality to this function. But we can take advantage of function overloading, to keep one copy of CvPlot::getBestDefender that is DllExport'ed, in the original signature.
It looks like this:
Code:
DllExport CvUnit* getBestDefender(PlayerTypes eOwner, PlayerTypes eAttackingPlayer = NO_PLAYER, const CvUnit* pAttacker = NULL, bool bTestAtWar = false, bool bTestPotentialEnemy = false, bool bTestCanMove = false) const;
CvUnit* getBestDefender(PlayerTypes eOwner, PlayerTypes eAttackingPlayer = NO_PLAYER, const CvUnit* pAttacker = NULL, bool bTestAtWar = false, bool bTestPotentialEnemy = false, bool bTestCanMove = false, bool bAssassinate = false, bool bClearCache = false) const; // Exposed to Python
Second line is our current code. First line is for compatibility.

It's possible to redirect DllExports to another function using a *.def file. Look at the changes in my latest commit for an example.
 
It's possible to redirect DllExports to another function using a *.def file. Look at the changes in my latest commit for an example.
What is this file and how do you manipulate it?
/trunk/Sources/CvGameCoreDLL.def

It looks like it's doing a redirect to the getBestDefender call that simply doesn't use the additional two parameters. I'm not quite understanding how this is supposed to fix the possibility that the EXE may get a different result from the function than the DLL does and thus go in two asynchronized directions in potentially assumed parallel processing paths, potentially leading to a disharmonious result in the EXE from what results up in the DLL.
 
What is this file and how do you manipulate it?
/trunk/Sources/CvGameCoreDLL.def
Reference: https://docs.microsoft.com/en-us/cpp/build/reference/exports?view=vs-2019

Our CvGameCoreDLL.def is currently used [exclusively] for aliasing export functions, for example getX() and getY() of CvPlot, CvCity and CvUnit, are aliased to their viewport counterparts. There are many cases viewport uses this file to alias functions, such as city looping (which are CvPlayer functions).

Code:
?getBestDefender@CvPlot@@QBEPAVCvUnit@@W4PlayerTypes@@0PBV2@_N22@Z=?getBestDefenderExternal@CvPlot@@QBEPAVCvUnit@@W4PlayerTypes@@0PBV2@_N22@Z
That line seems to be complicated (they are internal names, decorated by MSVC compiler, cf. https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=vs-2019 ), but it is essentially saying:
Code:
class CvUnit * CvPlot::getBestDefender(enum PlayerTypes, enum PlayerTypes, class CvUnit const *, bool, bool, bool)
=
class CvUnit * CvPlot::getBestDefenderExternal(enum PlayerTypes, enum PlayerTypes, class CvUnit const *, bool, bool, bool)
Do you spot the tiny little equal sign in the midst of that line?

Also, in the header, now we must DllExport getBestDefenderExternal and undo DllExport to getBestDefender (which we use internally and takes two additional boolean parameters).
That way, we are exporting getBestDefenderExternal and making the name getBestDefender an alias to it (from the exe's point of view).


10602

  • Fixed the DllExport CvUnit::getBestDefender
A small correction: CvPlot::getBestDefender :goodjob:
 
Last edited:
Reference: https://docs.microsoft.com/en-us/cpp/build/reference/exports?view=vs-2019

Our CvGameCoreDLL.def is currently used [exclusively] for aliasing export functions, for example getX() and getY() of CvPlot, CvCity and CvUnit, are aliased to their viewport counterparts. There are many cases viewport uses this file to alias functions, such as city looping (which are CvPlayer functions).

Code:
?getBestDefender@CvPlot@@QBEPAVCvUnit@@W4PlayerTypes@@0PBV2@_N22@Z=?getBestDefenderExternal@CvPlot@@QBEPAVCvUnit@@W4PlayerTypes@@0PBV2@_N22@Z
That line seems to be complicated (they are internal names, decorated by MSVC compiler, cf. https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=vs-2019 ), but it is essentially saying:
Code:
class CvUnit * CvPlot::getBestDefender(enum PlayerTypes, enum PlayerTypes, class CvUnit const *, bool, bool, bool)
=
class CvUnit * CvPlot::getBestDefenderExternal(enum PlayerTypes, enum PlayerTypes, class CvUnit const *, bool, bool, bool)
Do you spot the tiny little equal sign in the midst of that line?

Also, in the header, now we must DllExport getBestDefenderExternal and undo DllExport to getBestDefender (which we use internally and takes two additional boolean parameters).
That way, we are exporting getBestDefenderExternal and making the name getBestDefender an alias to it (from the exe's point of view).



A small correction: CvPlot::getBestDefender :goodjob:
Ok, but if the EXE is calling getBestDefender, it would never know to do so with the proper parameters for those final two bools, which could mean, if it is calling for getBestDefender in sync with processing in the DLL that tells the EXE to call it, for whatever reason, it's going to come up with potentially a very different result than what the DLL comes up with. This seems a good solution for now and we'll see if there are any bugs stemming from that result disagreement, but it's hard to understand why the EXE even needs to call for getBestDefender, and it could really be a reason for a mysterious problem or set of problems, like perhaps some of the reasons we see the plot list disagree with the units on what units are where.

Am I wrong here? I'm hoping I am.
 
I don't think the exe use the function for anything very important, as the exe does not handle AI decisions or unit movement.
The last bool is about clearing the cache or not, that is probably only needed in special cases and done when needed by the dll.
In any case, I don't think the exe would use the result in the same context as the dll in such a way that the dll code anywhere would depend on the exe to have the same result for it as the dll would get when clearing the cache.

This is only my intuition, I haven't looked deeper into it than what's been said in this forum lately.
 
Last edited:
Ok, but if the EXE is calling getBestDefender, it would never know to do so with the proper parameters for those final two bools, which could mean, if it is calling for getBestDefender in sync with processing in the DLL that tells the EXE to call it, for whatever reason, it's going to come up with potentially a very different result than what the DLL comes up with. This seems a good solution for now and we'll see if there are any bugs stemming from that result disagreement, but it's hard to understand why the EXE even needs to call for getBestDefender, and it could really be a reason for a mysterious problem or set of problems, like perhaps some of the reasons we see the plot list disagree with the units on what units are where.

Am I wrong here? I'm hoping I am.

If changes in the dll lead to problems with the exe those changes must be reverted if there's no possible workaround. Thats because we don't know what the exe does and the fact that we can't change the exe.
 
I don't think the exe use the function for anything very important, as the exe does not handle AI decisions or unit movement.
The last bool is about clearing the cache or not, that is probably only needed in special cases and done when needed by the dll.
In any case, I don't think the exe would use the result in the same context as the dll in such a way that the dll code anywhere would depend on the exe to have the same result for it as the dll would get when clearing the cache.

This is only my intuition, I haven't looked deeper into it than what's been said in this forum lately.

If changes in the dll lead to problems with the exe those changes must be reverted if there's no possible workaround. Thats because we don't know what the exe does and the fact that we can't change the exe.

Yeah, I'm just bringing up the possibility and it's good that y'all see that it COULD be one. Like you, I'm wondering what it could possibly need the function reported for. I'm wondering if it has something to do with controlling the art animation sequence in combat and may have something to do with the combat animation crash bugs we've never fully diagnosed. It very well could've been around the time that those new bools were added that we started having that occasional crash during combat animation. As Anq mentioned, there is a way to pass this information through a stored variable elsewhere, though it might be a little tricky with this in particular, without utilizing the new parameters. I might have to go in and see if I can work out how to go about that in a way that reliably works. It could possibly clear up those combat animation crashes.

The problem with saying "if changes in the dll lead to problems with the exe," is that it's almost impossible to know for sure that any given changes DO cause problems in the EXE. We already know there ARE some occasional issues we don't understand that can happen there and perhaps both of these issues help to narrow in on those.

What gets me is, IF I'm at all correct about the suspicion regarding the animation bug, shouldn't it just have been that the dllexport wasn't even in place? Without it being there, how would the 'new' function parameters even have created any change in the way the EXE processes, right? So I'm probably barking up the wrong tree. It's truly a question how we've gone so long without the export portion in place at all. Surely it really is NOT doing anything critical... Or is there a way that perhaps the DLLExport heading on the function declaration is just a 'note' and the EXE still accesses the function if it is there in the name and configuration it's calling for?
 
Any of you programmers know what I need to do to get my product working again?
upload_2019-6-23_12-58-20.png

I'm not sure how to get a product key. I thought this was free to use... Depending on how much it is, I could pay for the access I need, but if it's too much, this might mean I'm done here.
 
Any of you programmers know what I need to do to get my product working again?
View attachment 527512
I'm not sure how to get a product key. I thought this was free to use... Depending on how much it is, I could pay for the access I need, but if it's too much, this might mean I'm done here.
Maybe @alberts2 is using different version - Visual Studio 2019 (never version than you use) has Community edition.
 
Any of you programmers know what I need to do to get my product working again?
View attachment 527512
I'm not sure how to get a product key. I thought this was free to use... Depending on how much it is, I could pay for the access I need, but if it's too much, this might mean I'm done here.

The Enterprise version isn't free only the Community Edition is free.
 
The Enterprise version isn't free only the Community Edition is free.
Hmm... I guess I need to hunt down how to download the community edition then. I'll take a look. Thanks for the tip.
 
Top Bottom