- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This may sound a bit complex, but here is my problem. I am in the process of building a project that needs to use netcdf. I'm using an older build (3.6.3), which, when I build it with Fortran bindings requires the compiler switch '/iface:mixed_str_len_arg' to work correctly. I'm building them into static libraries so I can then include these in another project where I build a fortran DLL that. I then call this new DLL from a C# program. Passed variables all work now, except for arrays. They get passed into the C# program at the correct length, but the elements in the array are all 'Undefined address'. If I leave off the '/iface:mixed_str_len_arg' compiler switch, the NETCDF libraries won't work, and the string then get clobbered in the pass. And none of these problems existed until I added in these NETCDF libraries...without them everything works fine - except I need them for my project. Any thoughts? Am I going about this totally backwards? I am using Visual Fortran Composer XE 2011 with Visual Studio 2010.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My advice is to not use /iface, which changes the interface for all calls. Instead, declare INTERFACE blocks for the netcdf routines and add:
!DEC$ ATTRIBUTES MIXED_STR_LEN_ARG :: routinename
in each one. I'm a bit puzzled though - I would not expect a library to want that unless it was also using STDCALL. (Maybe you're using that and didn't mention it.)
I'm also puzzled about arrays being significant. Can you show some actual code with declarations on both the Fortran and C# side? Could it be that the arrays are not declared in C# in a manner consistent with Fortran?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve,
I miss spoke about the strings - I've got them passing correctly now. However, that compiler switch is the thing that is messing with my array pass. I am pretty far outside of my comfort zone, and I like the idea of the interface, so I'll give that a shot. My calls are fairly simple. The C# pass looks like this:
//Import DLL here [DllImport(@"Fortran_Built.dll", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] static extern void FORTSUB(ref float t0, ref float rh, [MarshalAs(UnmanagedType.LPStr)] string String1, [MarshalAs(UnmanagedType.LPStr)] string String2, float[] Array, ref int ierr);
with the call like this:
float t0=10.0f; float rh=75.0f; string inString1='This is the first string'; string inString2='This is the second string'; float[] array1= new float[31]; for (int i = 0; i < 31; i++) { array1 = 40.0f - i; } int ierr=0;
FORTSUB(ref t0, ref rh, inString1, inString2, array1, ref ierr);
The fortran is as follows:
subroutine FORTSUB(t0, rh, String1, String2, array1, ierr) !DEC$ ATTRIBUTES DLLEXPORT::FORTSUB !DEC$ ATTRIBUTES ALIAS 'FORTSUB':FORTSUB !This makes the DLL call available to other programs !We will try passing the string by reference !DEC$ ATTRIBUTES REFERENCE::String1 !DEC$ ATTRIBUTES REFERENCE::String2 character*255 String1,String2 real t0,rh real array1(31) integer ierr
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Add REFERENCE on the ATTRIBUTES line for the subroutine. By using /iface:mixed_str_len_arg, you get a length even with REFERENCE on the argument. It's weird, I know.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I made that change (!DEC$ ATTRIBUTES REFERENCE::ARRAY1), with a similar 'pass by reference' in the C# but it did not have any effect. Am I misunderstanding you? Is the problem that the array comes after the strings?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I want you to change:
!DEC$ ATTRIBUTES ALIAS 'FORTSUB':FORTSUB
to:
!DEC$ ATTRIBUTES REFERENCE, ALIAS 'FORTSUB':FORTSUB
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Sorry, my mistake. However, making that change had no effect. The array still comes through to the fortran subroutines with the correct dimension, but every element says 'Undefined address'. I'll try working the Interface angle and see what that does. Thanks for your help on this!
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maybe the issue is that the way you have the argument declared in C# isn't compatible with Fortran arrays. I am not familiar enough with C# to comment on that. In C I'd pass an array as "float *" or something like that. Do you know how C# is passing the array? (I assume you know that Fortran arrays are 1-based.)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I'm fair at C#, and I've done lots of C# - Fortran integration. It works surprisingly easy (and yes, I make sure all passed arrays are 1D). This all worked beautifully before I added in the NETCDF libraries...If I don't include those, I don't need the weird compiler directives (none of which seem to work), and everything works smoothly. I am thinking it falls back on the NETCDF build I am using, but I have had a really hard time coming up with a build I can do through VS...there is an incredible amount of info on building NETCDF, but almost nothing for building it through VS. I want to be able to test with 32 bit and 64 bit builds. Without reliable NETCDF libraries, this project won't go anywhere. And I am TERRIBLE at C programming, so it is really hard for me to try to pick through the build I do have..all very frustrating.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One thought - what other compiler options are you using, and which compiler was your NETCDF library built for? If you are mixing STDCALL and C, you will get stack corruption that can cause odd problems.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Everything was built through MSVS 2010 with the fortran compiles XE 2011. I did NOT set the STDCALL and C directives.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
But what about NETCDF? Can you provide a link to the exact library download you're using?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I followed the step-by-step instruction for building NETCDF 3.6.3 from the appendix D of the following link (http://www.fredwobus.com/research/wobus_2013_PhD_thesis_dense_water_cascading.pdf). As I've mentioned, NETCDF is out of my comfort zone. I the past I've used pre-built versions, but now I need a little more control.

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page