J,
I forgot to mention something important: your perl code is sending a
SAFEARRAY. Perl creates and sends a SAFEARRAY when you create a variant with
VT_ARRAY. However, you are not receiving variants containing SAFEARRAYs in
your C/C++.
Good luck.
Siegfried

-----Original Message-----
From: Siegfried Heintze [mailto:[EMAIL PROTECTED] 
Sent: Tuesday, June 07, 2005 11:50 AM
To: 'Japerlh'
Cc: beginners@perl.org
Subject: RE: Argument passing between perl and a C function.

J,
I assume you are (1) successful at calling this function calculate from
C/C++ and (2) implementing this in a local DLL. Can you post a fragment of
this C/C++ client code?

I believe that you are successfully calling calculate from C/C++ in spite of
the fact you are breaking the rules of COM and specifically Dispatch
interfaces. I believe that if you were to implement calculate in an
executable or remote DLL on a different computer, it would not work because
you are breaking the rules.

I think the source of your confusion is that the rules of C (which say to
pass an array just pass a pointer) are not the same as COM Dispatch
interfaces. In COM dispatch interfaces, you do not pass a pointer for the
purpose of passing an array. You only pass a pointer for the purpose of
receiving a single scalar back from Calculate. I'm using the work scalar to
include BSTRs (i.e., strings).

To make your function receive arrays work, you have two options:

(1) Change the array arguments in your C/C++ source code to be variants.
This gets a little complicated because you can pass a variant by reference
or by value and a variant can contain a SAFEARRAY or a reference to a
SAFEARRAY and you probably should insert the logic to detect this and act
accordingly. Insert the code in function calculate to extract the SAFEARRY
from the variant. If you are using C/C++ as a client in addition to perl,
you will have to change this client C/C++ code too. I'm sure perl can handle
this approach.

(2) Change the array arguments to pass an SAFEARRAY by reference instead of
wrapping it in a variant. The code generator in Visual Studio does not do
this completely. You will have to manually edit the IDL code. I suspect perl
can handle this approach, but I'm not sure how to make perl send a safearray
without wrapping it in a variant. I found this technique documented only in
one place years ago, but I tried it (not with perl though) and it did work
and it is more efficient.

Both approaches require that you will have to enhance function calculate to
extract/store elements from your safearray. This requires you become
intimate with Microsoft's special functions for SAFEARRAYs.

You can find lots of books (probably out of print, however) and online
documentation on manipulating safearrays in C/C++. They are painful to use
from C/C++, however. You cannot use the bracket operators ('[]') to
fetch/store array elements unless you have a special package that overloades
the operator[] in C++. Microsoft supplies no such package, however.

If you have trouble with SAFEARRAYS, I am available for consulting services
for a fee. I could write some sample code for you, for example.


Good luck,
Siegfried


-----Original Message-----
From: Japerlh [mailto:[EMAIL PROTECTED] 
Sent: Tuesday, June 07, 2005 1:23 AM
To: Siegfried Heintze
Cc: beginners@perl.org
Subject: Re: Argument passing between perl and a C function.

Sieg,

Thanks for your help.

I did not catch what you said.
Should I change that application written in C++?
Could you tell me something more about it?
Thanks in advance.

On 6/7/05, Siegfried Heintze <[EMAIL PROTECTED]> wrote:
> J,
> I just reviewed the notes I used to teach COM from. I'm feeling more
certain
> that if you want to pass arrays with the dispatch interface, you can
either
> pass a variant or pass a SAFEARRAY. You appear to be doing neither in your
> C++ code.
> Sieg
> 
> -----Original Message-----
> From: J aperlh [mailto:[EMAIL PROTECTED]
> Sent: Friday, June 03, 2005 12:05 AM
> To: Siegfried Heintze
> Cc: beginners@perl.org
> Subject: Re: Argument passing between perl and a C function.
> 
> Siegfried,
> 
> Thank you.
> I am sure it's a dispatch interface.
> 
> 
> On 6/3/05, Siegfried Heintze <[EMAIL PROTECTED]> wrote:
> > J,
> > Is this a custom interface or a dispatch interface? I assumed it was a
> > dispatch interface. Perl and many other languages like VB and javascript
> > work well with dispatch interfaces because dispatch interfaces were
> > specifically designed to accommodate languages like these.
> >
> > All dispatch interfaces are various implementations of IDispatch, a set
of
> > function prototypes defined my Microsoft.
> >
> > I think you have a custom interface because you are not using
SAFEARRAYs.
> I
> > doubt Win32::OLE can accommodate custom interfaces. Can you implement
your
> > object using a dispatch or dual interface? You might have to have the
> author
> > of your COM object wrap it in C++ with a dispatch interface so you can
> call
> > it from perl. Wraping it with a C++ dispatch interface is not hard with
> > Visual Studio's code generators. I would not want to do it without
visual
> > studio, however.
> >
> > Custom interfaces are a big problem. Not even microsoft's most recent
> > languages, VB.NET and C# can consistently call custom interfaces. I
would
> > not want to try to do so directly in perl.
> >
> > Siegfried
> >
> > -----Original Message-----
> > From: J aperlh [mailto:[EMAIL PROTECTED]
> > Sent: Thursday, June 02, 2005 7:59 PM
> > To: Siegfried Heintze
> > Cc: beginners@perl.org
> > Subject: Re: Argument passing between perl and a C function.
> >
> >
>
---------------------------------------------------------------------------
> > Thanks for you guys help.
> >
> > There is an application written in C language by my colleague.
> > We are not allowed to share this application for security reason.
> >
> > What I am going to do is to call a set of functions in this
> > application (OLE server) from a PERL script (OLE controller).
> >
> > So far, all the functions are works well, except a reference(pointer)
> > related functions:
> >
>
---------------------------------------------------------------------------
> > BOOL Calculate(BSTR* names, double* values, short number_of_names);
> > names: a list of names
> > values: a list of corresponding values,
> > number_of_names: size of the array
> >
> > I don't know that I should pass to this funtion.
> > Array reference or something else?
> >
> > I know that if the OLE controller is in C language, things will be
easier,
> > Passing the first element of the array to this function is ok
> >
> >
> >
> > On 6/3/05, Siegfried Heintze <[EMAIL PROTECTED]> wrote:
> > > J,
> > > You need more information about the function that is contained in the
> IDL
> > or
> > > the type library. Unfortunately, not all COM objects have an IDL file
or
> > > type library.
> > >
> > > Both the IDL file and the type library would tell us exactly what the
> "*"
> > > means in C because it is ambiguous. The "*" could mean we are passing
a
> > > single value by reference, or multiple values.
> > >
> > > I can tell you that it is not looking for a variant, however.
> > >
> > > Often COM uses a special data structure called a SAFEARRAY to pass
> arrays
> > so
> > > it could be that your function is looking for scalars, not arrays.
> > >
> > > Perhaps there is some documentation?
> > >
> > > S
> > >
> > > -----Original Message-----
> > > From: J aperlh [mailto:[EMAIL PROTECTED]
> > > Sent: Wednesday, June 01, 2005 8:44 PM
> > > To: beginners@perl.org
> > > Subject: Argument passing between perl and a C function.
> > >
> > > Argument passing between perl and C function.
> > >
> > >
> > > There is C function in a OLE server:
> > > What kind of variable should I pass to this function?
> > >
> #########################################################################
> > > BOOL Calculate(BSTR* names, double* values, short number_of_names);
> > >
> > >
> > > I tried the following script, but there is always an error like "Type
> > > mismatch" ...
> > > Is there any simple way to pass argument between perl and C function?
> > >
> #########################################################################
> > > #! perl -W
> > >
> > >
> > > use strict;
> > > use Win32::OLE;
> > > use Win32::OLE::Variant;
> > >
> > >
> > > my $names = Variant(VT_BSTR|VT_ARRAY, 3);
> > > my $values = Variant(VT_R8|VT_ARRAY, 3);
> > >
> > >
> > > $names->Put(['name1', 'name2', 'name3']);
> > > $values->Put([0, 0, 0]);
> > >
> > >
> > > my $ret = $app->Calculate($names, $values, 3);
> > >
> > > --
> > > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > > For additional commands, e-mail: [EMAIL PROTECTED]
> > > <http://learn.perl.org/> <http://learn.perl.org/first-response>
> > >
> > >
> > >
> >
> > --
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> > <http://learn.perl.org/> <http://learn.perl.org/first-response>
> >
> >
> >
> > --
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> > <http://learn.perl.org/> <http://learn.perl.org/first-response>
> >
> >
> >
> 
> --
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
> <http://learn.perl.org/> <http://learn.perl.org/first-response>
> 
> 
> 


-- 

Besh wishes,
Japerlh

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to