Re: Plugin Sample in C++ - IMPORTANT! SERIOUS ERROR!

2003-08-20 Thread Mark Wieder
Alexey-

Wednesday, August 20, 2003, 1:18:31 AM, you wrote:

ANV> | virtual int TBP_EXPORT GetDataByID(int ID, void* B, int BSize) = 0;

Making the member functions abstract won't hurt, but I think they will
only help debug TB itself, since instantiation isn't done within the
DLL. Nonetheless, it seems like good practice here.

MW>> My intention here is 1) to cut down the size of the code and increase
MW>> execution speed by not instantiating new objects unless absolutely
MW>> necessary, and 2) to minimize the chances of creating a problem
MW>> interfacing with Delphi with name mangling and such, since this is a
MW>> shared library and not a standalone application. Obviously both
MW>> approaches will work.

ANV> Well. I agree with you at this point. My intention is to make most faithful
ANV> translation from Delphi to CPP, and also to keep the things which is may be not
ANV> so necessary, but just make more comfort. By this reason, for example, I leave
ANV> the absolute definitions of enum's members, like:

ANV> ,-
ANV> | enum midx {
ANV> |   midxSubject = 1,
ANV> |   midxDate= 2,
ANV> |   midxComment = 3,
ANV> |   midxInReplyTo   = 4,
ANV> |   midxMessageID   = 5,
ANV> |   midxNewsgroups  = 6,
ANV> `-

The only problem here is what happens when ritlabs decides to redo
things and insert, for example, midxMessageNumber in between
midxMessageID and midxNewsgroups. If you have things hardcoded you
will need to renumber everything past entry six. If you just declare
the first then you simply insert a line in your source.

ANV> This is well if there is no Interface definition, because it seems to be pure
ANV> C++. I more intent in this case to use more code on ISO C++. It has nothing with
ANV> vcl or mfc - just standard C++ library. For example, if I use CString - woe to
ANV> me if compiler can't hold it! But if I use std::string - woe to compiler who
ANV> can't compile it!



Actually, given

struct xyz : public IUnknown
{
}

the line between struct and class is getting very blurred...

There's another anomaly in my source: I typedef'd PChar as char*
instead of unsigned char* because Codewarrior complained if I didn't
explicitly cast the result. It seemed easier just to say char and hope
there weren't any repercussions down the line.

-- 
-Mark Wieder

 Using The Bat! v1.63 Beta/7 on Windows 2000 5.0 Build 2195 Service Pack 2



http://www.silverstones.com/thebat/TBUDLInfo.html


Re[2]: Plugin Sample in C++ - IMPORTANT! SERIOUS ERROR!

2003-08-20 Thread Alexey N. Vinogradov
Hello, Mark. 
You wrote in 

ANV>> 1. Strictly speaking, the interface is defined as struct. (there is line in the
ANV>> header: #define interface struct. So, I would change your code by using word
ANV>> "struct" if "interface" is undefined, and also "public:" is not necessary in
ANV>> this case. But, repeat, this is only cosmetic.

MW> Well, I could have sworn that, strictly speaking, functions were
MW> illegal as struct members. However, that syntax seems to pass my
MW> compilers without problem, so I have now changed it. Yes, it *is* just
MW> cosmetic, but I wouldn't have made it a class if I thought I could
MW> have gotten away with a struct.

This was no more than a line from VC98\Include\objbase.h (and also from some
others standard microsoft headers):

#define interface struct

Of course, it may be not so good to define structure contains methods. Also I
think it can be noticed that interfaces usually declared as pure abstract
classes. Of course it is no difference for working code, but it would be more
informative for debugging during initial code creation. I mean, that if user
will accidentally define a variable of class ITBPDataProvider, he will receive
rather more informative message that it is unable to substantiate fully abstract class,
then simple "unresolved external" or that function declared but not defined. It
will help to beginners to differentiate between logical and technical bugs. So,
for this purpose I think it is also useful to change the declaration of
ITBPDataProvider to be like:

,- [ just add " = 0" to make every function abstract ]
| #if defined(interface)
| interface DECLSPEC_UUID("9DD91B89-A551-4180-8A81-2CCF584CD4BF") ITBPDataProvider
| : public IUnknown
| #else
| struct ITBPDataProvider // (also must be ): public IUnknown
| #endif
| {
| public:
| virtual int TBP_EXPORT GetDataByID(int ID, void* B, int BSize) = 0;
| virtual int TBP_EXPORT SetDataByID(int ID, void* B, int BSize) = 0;
| virtual int TBP_EXPORT GetIntValue(int ID) = 0;
| virtual int TBP_EXPORT SetIntValue(int ID, int Value) = 0;
| virtual int TBP_EXPORT GetIDType(int ID) = 0;
| virtual int TBP_EXPORT ItemCount() = 0;
| virtual HRESULT TBP_EXPORT ExecuteMacro(void* AMacro, int 
MaxLen,ITBPDataProvider* x) = 0;
| };
`-


MW> My intention here is 1) to cut down the size of the code and increase
MW> execution speed by not instantiating new objects unless absolutely
MW> necessary, and 2) to minimize the chances of creating a problem
MW> interfacing with Delphi with name mangling and such, since this is a
MW> shared library and not a standalone application. Obviously both
MW> approaches will work.

Well. I agree with you at this point. My intention is to make most faithful
translation from Delphi to CPP, and also to keep the things which is may be not
so necessary, but just make more comfort. By this reason, for example, I leave
the absolute definitions of enum's members, like:

,-
| enum midx {
|   midxSubject = 1,
|   midxDate= 2,
|   midxComment = 3,
|   midxInReplyTo   = 4,
|   midxMessageID   = 5,
|   midxNewsgroups  = 6,
`-

and not

,-
| enum midx {
|   midxSubject = 1,
|   midxDate,
|   midxComment,
|   midxInReplyTo,
|   midxMessageID,
|   midxNewsgroups,
`-

This is, of course, not necessary, but if I want quickly to found numberic value
of midxNewsgroups - I can just found it's definition in the header, what is not
so easy in the second case.

MW> My idea here was to write as much simple C, not C++, code as possible
MW> to minimize the chances of having to modify the code for other
MW> compilers (i.e. not using vcl or MFC objects). This is the same
MW> reasoning as above in using a struct instead of a class.

This is well if there is no Interface definition, because it seems to be pure
C++. I more intent in this case to use more code on ISO C++. It has nothing with
vcl or mfc - just standard C++ library. For example, if I use CString - woe to
me if compiler can't hold it! But if I use std::string - woe to compiler who
can't compile it!

-- 
Sincerely,
 Alexey.
Using TB 2.0b2 on WinXP Pro SP1 (2600), spelling by ORFO2002 (CSAPI) 
..with Kaspersky Antivirus Plugin (ver 3.5 Gold) & antispam filter BayesIt! 0.3b

   mailto:[EMAIL PROTECTED]



http://www.silverstones.com/thebat/TBUDLInfo.html


Re: Plugin Sample in C++ - IMPORTANT! SERIOUS ERROR!

2003-08-20 Thread Mark Wieder
Alexey-

Thanks. Good points.

(Mark sheepishly says)
No, I didn't test under VC++, I just trusted the code you posted
earlier and extrapolated from there. I'll look at changing the header
and repost it. This is the first time I've worked at including the
macro API and I have to say I find it pretty ugly.

One thing I'd like to see is a COM-type query function that would
enumerate the macro strings rather than making me catenate them at
design time. And Stefan's lack of comments makes TBP_ExecMacro a bit
of a joke as example code.

Also, tpxTotalPages and tpxTracking both evaluate to 248 and
tpxCurrentPage and tpxQuoteStyle both evaluate to 249. This can't
possibly be right, can it?

ANV> This is main and critically serious error. Please, refer to
ANV> other variants of API (which I
ANV> referred on the top of the letter) and work more... I warn you about it because
ANV> giving the wrong headers from the beginning can prefer many from writing such
ANV> plugins.

Again, a very good point.

ANV> 1. Strictly speaking, the interface is defined as struct. (there is line in the
ANV> header: #define interface struct. So, I would change your code by using word
ANV> "struct" if "interface" is undefined, and also "public:" is not necessary in
ANV> this case. But, repeat, this is only cosmetic.

Well, I could have sworn that, strictly speaking, functions were
illegal as struct members. However, that syntax seems to pass my
compilers without problem, so I have now changed it. Yes, it *is* just
cosmetic, but I wouldn't have made it a class if I thought I could
have gotten away with a struct.

ANV> 2. If you write on CPP, why are you using malloc and free? Let use new and
ANV> delete instead! CPP is not C, and although malloc and free still works, they are
ANV> deprecated in CPP. Of course, this is also just cosmetic, and somebody who will
ANV> use it will change it, but anywhere...

The main reason that malloc and free are deprecated is that their
usage can result in sloppy code that causes memory leaks. I've tried
to be very careful to free anything that was allocated and the one
case in which a memory block is not explicitly freed is notated in the
source (as it is in your source as well). Note that new without a
corresponding delete will cause the same memory leak as malloc without
a corresponding free.

My intention here is 1) to cut down the size of the code and increase
execution speed by not instantiating new objects unless absolutely
necessary, and 2) to minimize the chances of creating a problem
interfacing with Delphi with name mangling and such, since this is a
shared library and not a standalone application. Obviously both
approaches will work.

My idea here was to write as much simple C, not C++, code as possible
to minimize the chances of having to modify the code for other
compilers (i.e. not using vcl or MFC objects). This is the same
reasoning as above in using a struct instead of a class.

-- 
-Mark Wieder

 Using The Bat! v1.63 Beta/7 on Windows 2000 5.0 Build 2195 Service Pack 2




http://www.silverstones.com/thebat/TBUDLInfo.html