On Wed, 30 Jul 2003 [EMAIL PROTECTED] wrote:
> On Wed, 30 Jul 2003 00:10:48 -0500 (EST), Kenneth Chiu wrote
> > On Wed, 30 Jul 2003 [EMAIL PROTECTED] wrote:
> > > On Tue, 29 Jul 2003 21:08:35 -0500 (EST), Kenneth Chiu wrote
> > > > On Tue, 29 Jul 2003 [EMAIL PROTECTED] wrote:
> > > >
> > > > > Hi all,
> > > > >
> > > > > Passing arrays as parameters to a method
> > > > > ----------------------------------------
> > > > > Doing this C++ differs from Java. Usually in C++ we pass the size of
> the
> > > > > array in another parameter so that inside the method it know the size
> of
> > > the
> > > > > array.
> > > > >
> > > > > In Java this is not a problem because an Array itself is a class that
> has
> > > the
> > > > > size. So a method in java,
> > > > > int EchoIntArray(int []) corresponds to int EchoArray(int
> [],
> > > int)
> > > > > in C++.
> > > > >
> > > > > Suppose some one needs to write a web service for this method and the
> > > method
> > > > > signature that the WSDL describes corresponds to the method signature
> in
> > > Java
> > > > > exactly but not the C++ one.
> > > > >
> > > > > So how should a C++ developer implement his service corresponding to
> the
> > > > > WSDL ?
> > > > >
> > > > > This way that we (Axis C++) asks the C++ web service developer should
> be
> > > > > decided in order to improve Wrapper Class Generator (WCG) to handle
> > > passing
> > > > > and returning arrays from methods.
> > > > >
> > > > > I find that we can give 2 solutions,
> > > > >
> > > > > 1. Introduce Axis C++ own Array class. So the method signature becomes
> > > > > int EchoIntArray(AxisArray a)
> > > > >
> > > > > 2. Ask the C++ developer to specify the meaning of other parameters by
> > > using
> > > > > a predefined Axis C++ macro. Then the method signature becomes,
> > > > > int EchoIntArray(int [], ARRAYINSIZE int);
> > > > >
> > > > > Which is the best option to choose. IMO I like second.
> > > > >
> > > > > Also if you find any other solution please discuss.
> > > > >
> > > > > Comments on this is very much appreciated.
> > > >
> > >
> > > > I suggest 1, or use std::array, simply because number 2
> > > > seems error-prone. Also, if you encapsulate the array in an
> > > > object, you can add range checking. You can
> > > > #ifdef-out the range-checking in the release build.
> > >
> > > I am not aware of an array class in STL. you must be refering to
> std::list.
> >
> > Sorry, I meant std::vector (there is std::valarray, but it's
> > probably not appropriate).
> >
> > > Anyway we hope to allow passing most of STL types as parameters as it is.
> > > When we allow this anyone can pass a std::list or std::map (etc) to a
> method
> > > as parameters. Only thing is we have to improve the Wrapper Class
> Generator
> > > (WCG) to use Axis implimented Serializers and Deserializers for each of
> those
> > > STL types.
> > >
> > > I too like if we can ask C++ web service developers to use std::list
> instead
> > > of an array. If so we (the WCG) can just forget about handling arrays.
> > >
> > > But usually its unlikely that a C++ developer use a std::list when he
> wants
> > > to pass an array of integers (list<int> instead of int[]) but array of
> > > complex types (say list<Address> instead of Address[]) is OK.
> >
> > I think it depends. If I'm convinced through profiling that
> > performance is an issue, I would just use a very thin wrapper:
> >
> > template <typename T>
> > class Array {
> >
> > public:
> >
> > explicit Array(int size) : m_data(new T[size]), m_size(size) {}
> >
> > ~Array() {
> > delete [] m_data;
> > }
> >
> > T& operator[](size_t i) {
> > #ifdef AXIS_DEBUG
> > // Or consider throwing.
> > assert(i < m_size);
> > #endif
> > return m_data[i];
> > }
> >
> > // Probably want a const version too.
> >
> > private:
> >
> > T *m_data;
> > int m_size;
> > };
> >
> > I try to avoid passing naked, dynamically-sized arrays.
> >
>
> this is very good than using stl::vector
>
> But if some one has already developped a set of methods and wants to expose
> them
> as web services he must be able to do that with least effort.
>
> say, He has a method,
>
> int* methodthatreturnsandpassesarrays(int* arr, int insize,
> int*outsize);
>
> If we use Array class he has to write a wrapper method to this
>
> Array* methodthatreturnsandpassesarrays(Array* ar)
> {
> int retsize;
> int* ret = methodthatreturnsandpassesarrays(ar->GetArray(), ar-
> >GetSize(), &retsize)
> Array* retA = new Array<int>(retsize);
>
> loop to intialize retA from ret or memset ...
> delete [] ret;
> return retA;
> }
>
> If we use 2 nd approach, the wrapper is not needed, only thing he has to do
> is to add few macros
> that only WCG recognizes.
>
> int* methodthatreturnsandpassesarrays(int* arr, INARRAYSIZE int
> insize, RETARRAYSIZE int*outsize);
>
> In case if the method has many/fewer parameters or different parameter order
> he will have to
> write a wrapper method that will be simple. for example if the above method
> written like,
>
> int* methodthatreturnsandpassesarrays(int* arr, char c, int insize,
> int* outsize, Address* ad);
>
> the wrapper method will be,
>
> int* methodthatreturnsandpassesarrays(int* arr, INARRAYSIZE int
> insize, char c, Address* ad, RETARRAYSIZE int*outsize )
> {
> return methodthatreturnsandpassesarrays(arr, c, insize,
> outsize, ad);
> }
>
> What do you think ?
Ah, I see. I understand the problem better now. I think
that you can do both. That is you can have an AxisArray, or
std::vector. If the user has an existing pointer+size
method to expose, you can generate the additional code for
that. If the user is willing to convert to AxisArray, you
just use that directly. For example, the wrappers might
look like:
wrapper_for_pointer_plus_size(...) {
AxisArray<int> a = ...;
original_func(a.ptr(), a.size());
}
wrapper_for_axis_array(...) {
AxisArray<int> a = ...;
original_func(a);
}
Also, how sophisticated will this WCG be? You are
generating it from annotated C++ class definitions? It
seems that it could recognize the case above. If you are
generating wrapper code anyway, you could easily shift the
parameters anyway:
int* methodthatreturnsandpassesarrays(int* arr, char c,
INARRAYSIZE insize, OUTARRAYSIZEE* outsize, Address* ad);
A couple other points. I apologize in advance if these have
already been discussed in detail, or you are already well
aware of them.
Passing Arrays
--------------
The first is that I'm uncertain how often C++ programmers
actually pass dynamically-sized arrays as a pointer + size.
My sense is that the first reaction of experts on groups such as
comp.lang.c++.moderated upon seeing such code is to ask,
"Why are you not using std::vector?" The answer is usually
something about performance, to which the response is
usually something about "Premature optimization is ...", etc.
Using naked pointers also makes it difficult to write
exception-safe code. For example:
void
A::foo(...) {
int *array = new int[array_size];
// In here, I must make sure that _all_ exceptions
// are caught, so I can delete array if necessary.
}
Even more problematic is stuff like:
int size;
some_func(method_that_returns_a_pointer(&size), size,
some_other_func());
The programmer probably intends for some_func() to delete
the array returned by method_that_returns_a_pointer().
Since order of evaluation is unspecified, it's possible that
some_other_func() will throw _after_ method_that_returns_a_pointer()
is called. In this case, it's impossible to clean-up.
There is an idiom in C++ known as RAII (Resource Acquisition
Is Initialization) which is used to take care of these kinds
of problems.
Memory Management
-----------------
The second is to ask what is the memory management model?
That is, who owns arrays passed in and arrays returned?
Memory problems are often considered the bane of C
programming, but things such as smart pointers can improve
the situation somewhat.