Passing arrays to Fortran COM methods

Passing arrays to Fortran COM methods

I'm having problems getting com to work. Specifically, when I create a method with the fortran com server wizard I can't get the dam thing to work with arrays. Even more specifically, I create the method via the new button. I then highlight the new method name and hit new again. With argument specified I hit ok which causes the argument operand properties dlg to be displayed. I then describe the data type as real(8) and check the array argument check box. I set the rank to 1 and the dimension from 1:6. I then select save and port in the appropriate subroutine from the +.f90. I can compile with no problems. Now for where the problem manifests itself.

In my VC++ client. I've done the necessary steps to get an appropriate pointer to the interface. When I try to call the function that takes an array as an argument through the interface with an appropriately defined array and compile, I get an error stating 'cannot convert parameter 1 from 'double [6]' to 'struct tagSAFEARRAY *'. If I type cast the array to (SAFEARRAY *) I can get it to compile but when I step into the FORTRAN com routine that uses the array I get the runtime error Access Violation when I try to use the array. So what's going on. A prompt response would be greatly appreciated

Ralph Mader

My compiler version: Compaq Visual Fortran Professional Edition Version 6.5
Operating system: Windows NT 4.0 with service pack 6
Processor: GenuineIntel Family 6 Model 6 466 MHz Stepping 10

3 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hi Ralph,

Case 1: Your object's interface is marked dual or oleautomation. i.e., the CS Wizard property page for the interface has "Uses only Automation data types" selected - note this is defaulted by the "Dual Interface" selection). In this case, the method is expecting a SAFEARRAY pointer not a C style array (like "double stuff[6]"). And as the compiler says (and your reinterpret_cast found), it's not possible to cast from a C style array to a SAFEARRAY* . You should create a SafeArray using the appropriate SafeArrayXxx API functions or just create a SafeArray struct that wraps your C style array and pass that.

Case 2: Your COM object's interface is not marked dual or oleautomation. Note that this implies that you will use standard (MIDL based) marshalling or guarantee that COM method calls will not be made across context (apartment) boundaries. In this case, the idea is that you could use C style arrays whose IDL would look something like

HRESULT foo1 ( [in] long Elems[6] );
or
HRESULT foo2 ( [in] long cbElems,
[in, size_is(cbElems)] long *pElems );

and call something like

long stuff[6] = {1, 2, 3, 4, 5, 6};
pITest->foo1(stuff);
pITest->foo2(6, stuff);

But even when the CS Wizard has the interface properties set for non-oleautomation compatible data types, it seems that the CS wizard still generates code for a SAFEARRAY*. In which case you must edit some of the DO NOT EDIT files (IDL at least) if you absolutely want to use this approach. Maybe Leo can comment here on CS Wizard support for arrays in the absence of the oleautomation attribute.

If it were me, I'd stick to using the oleautomation attribute ("Uses only Automation data types"). The upside is support for VB clients, SafeArrays have a much better language mapping to f90 (particularly for multidimensional arrays), and the ease of type lib marshalling.

hth,
John

Hi,

John is correct concerning Safe Arrays. The Fortran COM Server Wizard currently supports only Safe Arrays for array arguments, not C Arrays.

Regards,
Leo

P.S. This serves as my reply to #CVF13221 also...

Leave a Comment

Please sign in to add a comment. Not a member? Join today