As pointed out in this thread:
http://www.sparxsystems.com.au/cgi-bin/yabb/YaBB.pl?board=general;action=display;num=1168551310EA does not produce the correct code in some cases when using Macros for the __declspec qualifiers (C++).
This problem refers to cases where #define Macros are being used for alternate __declspec declarations within library headers that are meant for both import and export of interfaces.
Consider a Macro defined like this:
#ifdef MY_FOO_LIB
#define MY_FOO_API __declspec(dllexport)
#else
#define MY_FOO_API __declspec(dllimport)
#endif
Then consider a class defined like that:
class cMyFoo : public cSomeExternalClass {
public:
MY_FOO_API cMyFoo();
virtual MY_FOO_API ~cMyFoo();
void* MY_FOO_API bar();
MY_FOO_API class cMyBar {/* ... */} m_bar;
};
If this gets imported to EA, all the methods get tagged values 'DeclMacro1' with the value 'MY_FOO_API'. With one exception: the constructor doesn't get this tagged value! (1). Also the attribute m_bar doesn not get the tagged value. (3)
When I then regenerate the code, I get this (comments added):
class cMyFoo : public cSomeExternalClass {
public:
cMyFoo(); // (1) error: MY_FOO_API missing
virtual MY_FOO_API ~cMyFoo(); // correct - but only works because declared as virtual!
void MY_FOO_API *bar(); // (2) error: the location of MY_FOO_API is wrong (between 'void' and the '*') - because of this it is being ignored!
class cMyBar {/* ... */} m_bar; // (3) error: MY_FOO_API missing
};
Problems (1) and (3) appear to be caused by the fact 'MY_FOO_API' happens to be the first symbol on the line. Adding those tagged values manually does fix the code generation for the constructor, but not for the attribute (see (2)!)
Problem (2) appear to be caused by EA's ignorance of placement rules for __declspec macros: the type definition has to appear either in front or behind '__declspec'. This is, including the '*' or '&', if present. So,
MY_FOO_API void* bar(); would also work.
EA appears to assume that any use of __declspec macros require a type (or at least some kind of symbol) in front of the macro. This is wrong. Both constructors and attribute declarations might require the Macro to be the very first symbol - and possibly destructors too, unless they are virtual. As a matter of fact, the __declspec macro can
always be used as the first symbol in line - however, in that case it gets completely ignored by EA import!
There are two things that need to be fixed:
1. Code import should recognize Macros even if they're the first symbol of the declaration.
2. Code export should place those macros either at the start of the declaration, or it should remember it's placement from import and use that information. Since it is possible different compilers treat __declspec slightly different, the latter approach would be preferrable.
The second point is the more important one since it is not possible to automatically generate correct code until this is fixed. The first one can be fixed manually, but I consider it severe since it causes hard to discover problems for those who are not aware of the bug - I know it took me the better part of a day to analyse it.
P.S.:
1. I just reported this as a bug, referring to this topic.
2. If anyone knows a good solution to problem (2), please let me know. (And no, I don't consider using typedefs a good solution, as a matter of fact I stumbled over this problem exactly because I wanted to reduce the number of typedefs being used within the project ... )