PDA

Click to See Complete Forum and Search --> : ATL COM troublesome


ZaidGS
Mar 24th, 2004, 02:54 PM
my objective is to interface some class,
as a dll made using vc++, for use in vb.

but i'm having a lot of trouble.

i use the ATL COM appWizard. (i use defaults
.ie. MFC not supported)

here are my two biggest problems so far:
(1) [UNRESOLVED]
after i define classA, and add methodes
and properties to the IclassA,
i want in vb pass it (either by reference or
value, whatever works)
like this:


Dim x as classA 'class defined in vc++
Dim y as New classB 'this class also defined in vc++
y.SomeFunction x, "hi", 3 'one parameter is classA


how could i define SomeFunction so that it
accepts that class as parameter.

(2) [RESOLVED]
my other problem is that,
one function that i have,
needs to accept a string.
i used LPSTR, as type
for that parameter.
each time i call that fuction, the program gives
a message box saying:
"runtime error - automation error -
the object invoked has disconected from its client"
and then quits.
i tried using char*, and CString, didnot work either (those didnot
even compile with me).

what could be wrong ?!?!

i use this ATL COM wizard without fully
understanding what code it writes, and to
some extent i find it impossible (well, caused me a lot of unfixable bugs) to
manually modify the code.
thats why each time i want to make a change to my
interface (like removing some function, or property
or change types of parameters)
i have to start all-over.
(nah, im not that stupid, i have functional C++
versions seperately, the COM just uses them)

could anyone help me in any way.

thanks for bothering to answer :D :blush:

ZaidGS
Mar 25th, 2004, 06:32 AM
ok, later today, i tracked down
my "object invoked disconneted from its client"
which happens when i use LPSTR to this function call:
(which causes crashing)


LPSTR strmid(LPSTR str,const size_t start,const size_t len){
LPSTR a="";
strncpy(a,str+start-1,len);
return a;
}


which i made to be a subsitute for the
vb MID(STRING, START, LENGTH) statement,
which extracts a part of a string.

the "strncpy(a,str+start-1,len)" statement is the one to crash.
can anyone tell me what this statement should be ?!?!

azteched
Mar 25th, 2004, 09:00 AM
Uhm ok.

1. It's a COM DLL, so use BSTR's for your string types. VB uses BSTR's internally anyway.

2. strmid:

your string 'a' isn't long enough to hold the string you're copying into it, since you assign a to ""..

do something like:

char *a = new char[strlen(str)+1]; //remembering null termination

Since this is a COM DLL I would really use BSTR for your strings, and use the SysAllocString etc functions to manage the memory. At least, in my experience, it works.

ZaidGS
Mar 25th, 2004, 12:18 PM
i tried using this code:

LPSTR strmid(LPSTR str,const size_t start,const size_t len){
LPSTR a=new char [255];
strncpy(a,"",255);
strncpy(a,str+start-1,len);
return a;
}


but guess this code causes
memory leaking.
how can i stop that ??!

ok, i'll try using BSTR sometime later,
dont think this will interfere with my
current questions.

azteched
Mar 25th, 2004, 12:52 PM
strncpy(a,"",255);

You don't want this. I think your maths for the position is a bit off too..

Here is a midstr function that works iirc:



char *midstr(char *s, int start, int num){

char *mst = new char[num+1];

strncpy(mst, s+start, num);

mst[num] = 0;

return mst;
}



note that strncpy does not null-terminate unless num>strlen(s) - if you want a midstr function then num should never be > strlen(s), so the addition of a null is required.

ZaidGS
Mar 25th, 2004, 01:05 PM
the wrong thing with my previous code is the memory leak,
the:
strncpy(a,"",255);
has a reason: to fill next 255 bytes with null characters.

azteched
Mar 25th, 2004, 01:31 PM
Why fill the entire string with nulls when you only need one?

To avoid memory leaks, you'd have to pass the string back to the dll for deletion once the client is done with it. Either that or have the client pass in a preallocated buffer.

Anyway, is this function supposed to be used by the VB program? If so the function signature should be different..if not there's no problem over memory, the calling c++ code can delete when it's ready.

ZaidGS
Mar 25th, 2004, 03:24 PM
this strmid function is not exposed in the interface,
its just used for internal string manipulation.
i just fill with nulls, to avoid the need for null terminating manually,
not something very important.

i use this function in context like:

if ( strcmp( strmid( STRING, 3, 2 ) , "XX" ) == 0 ) {
//something happens
}
//or
t = mid( STRING, 3 ,2 )


now after such a statement, a memory leak occurs.

azteched
Mar 25th, 2004, 03:43 PM
Yes it will :)

Solutions:

1. the "C" approach: store the return value of strmid in a variable and use delete[] on the variable after you're done with it.

2. the C++ approach: use std::string or similar and the memory will be automatically released when the std::string object is destroyed (via the destructor).

The C++ approach is cleaner.

ZaidGS
Mar 26th, 2004, 05:58 AM
ohh, my memory leak problem resolved.
in fact the problem was a code problem, not
a COM problem.
i feel stupid that i didnt make it right after i discovered
where the problem was.

anyways, back to COM,
can anyone tell me how to pass an
ATL class as a parameter in vb.
(ie. my first question)

azteched
Mar 26th, 2004, 06:34 AM
an IClassA* ?

ZaidGS
Mar 26th, 2004, 12:42 PM
Originally posted by ZaidGS
(1) [UNRESOLVED]
after i define classA, and add methodes
and properties to the IclassA,
i want in vb pass it (either by reference or
value, whatever works)
like this:


Dim x as classA 'class defined in vc++
Dim y as New classB 'this class also defined in vc++
y.SomeFunction x, "hi", 3 'one parameter is classA


how could i define SomeFunction so that it
accepts that class as parameter.


yes! an IclassA* (but guess i tried that, but didnt compile it says:
error MIDL2025 : syntax error : expecting a type specification near "IclassA")
i have two ATL classes,
classA, and classB
and their (dual) interfaces IclassA, and IclassB.
now, classB should have "SomeFunction"
where its first (or whatever) parameter is
an instance of classA (which is x in my example.)