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>