Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

transferring several strings from VS 2013 to Intel Fortran dll

Gerrit_V_1
Beginner
682 Views

Hi, I 'm stuck when trying to transfer more than one string from VS 2013 to Intel Fortran dll. One string and some data arrays are transferred correctly and removing the second string the program works fine, but adding the second string an exception is trown. Attached is a small program that shows the problem. The first string is correctly transferred to the dll, but the second is empty . When I remove the reference to that filename it contains rubbish, or an exception is raised "address is not found". I'm looking forward for your suggestion to solve this nasty problem.

Any suggestion is very welcome.

Gerrit Verboom

0 Kudos
1 Solution
Steven_L_Intel1
Employee
682 Views

FIrst, the Fortran code is being called from Visual Basic. This is what I wanted clarified when I remarked that saying it was called from "Visual Studio" was not informative.

Because you add the REFERENCE attribute to FLN1 and FLN2, Intel Fortran is not expecting a length to be passed and uses the length you declared. I am not sure what you read that may have misled you, but this is a complex subject with many combinations and it is easy to get confused. If you do pass lengths, they go at the end of the argument list and are passed by value.

I noticed that you use the STDCALL attribute on the routine but not REFERENCE. This means that the Fortran routine expects all the arguments to be passed by value (which you do), but that also means you can't return any results to the VB caller, so I don't think this is what you want. I'd suggest adding REFERENCE to the attributes for subroutine SOURCE1 and remove the ByVal from all the argument specifications in the VB module EXCEPT for the strings, which must remain ByVal.

In the VB project, I recommend that you go to the Compile property page and set Target CPU to "x86". I have seen issues with "Any CPU" when calling 32-bit DLLs on a 64-bit Windows system.

Lastly, I see that you put in INCLUDE lines for both link_fnl_shared.h and link_fnl_shared_imsl.h. Only one of these should be used - I would recommend link_fnl_shared.h.

View solution in original post

0 Kudos
9 Replies
IanH
Honored Contributor II
682 Views

(I see no attached "small program".)

0 Kudos
Steven_L_Intel1
Employee
682 Views

It's also not clear what you mean by "VS2013", since that's a development environment not a language. You are probably not passing the strings with lengths properly. You will need to show us both the Fortran routine you are calling (that it is in a DLL is not important) and the code that is calling it.

0 Kudos
Gerrit_V_1
Beginner
682 Views

Good morning Steve,

Thanks for responding, I meant to add the program, but something went wrong. With VS2013 I meant Visual Studio 2013. The Fortran dll is build with Intel Visual Fortran Composer 2013 SP1.

I indeed added the length to the dll-call, I understood this is required. A previous project worked fine with fixedlength string AND passing the length parameter. So, I was surprised by your suggestion to remove the length parameter from the interface.

I removed the length parameter and it works fine. Many thanks.

But can you please shed some light on this: fixedlength string, no zero character at the end and no length parameter in the interface. Am I reading old instructions or mis-understood?

Again many thanks for your help and looking forward for your reply.

Regards,

Gerrit V.

0 Kudos
Steven_L_Intel1
Employee
683 Views

FIrst, the Fortran code is being called from Visual Basic. This is what I wanted clarified when I remarked that saying it was called from "Visual Studio" was not informative.

Because you add the REFERENCE attribute to FLN1 and FLN2, Intel Fortran is not expecting a length to be passed and uses the length you declared. I am not sure what you read that may have misled you, but this is a complex subject with many combinations and it is easy to get confused. If you do pass lengths, they go at the end of the argument list and are passed by value.

I noticed that you use the STDCALL attribute on the routine but not REFERENCE. This means that the Fortran routine expects all the arguments to be passed by value (which you do), but that also means you can't return any results to the VB caller, so I don't think this is what you want. I'd suggest adding REFERENCE to the attributes for subroutine SOURCE1 and remove the ByVal from all the argument specifications in the VB module EXCEPT for the strings, which must remain ByVal.

In the VB project, I recommend that you go to the Compile property page and set Target CPU to "x86". I have seen issues with "Any CPU" when calling 32-bit DLLs on a 64-bit Windows system.

Lastly, I see that you put in INCLUDE lines for both link_fnl_shared.h and link_fnl_shared_imsl.h. Only one of these should be used - I would recommend link_fnl_shared.h.

0 Kudos
DavidWhite
Valued Contributor II
682 Views

My experience with VB and VBA interfacing to a Fortran DLL is that the string in VB needs to be the correct size as specified in Fortran.

So for your 10 character strings in Fortran, you need to fully fill the string variables with blanks to 10 characters before passing them.

I'm not sure what you're trying to do when you pad your strings.  Since Fortran does not use null delimited strings, I don't think it makes sense adding a null character and then padding the string with blanks (if that's what your code is doing - I wasn't quite sure).

In my applications, calling Fortran from Microsoft Excel VBA and from the Honeywell VB code (which doesn't seem to be standard VB), padding the string to the full length with blanks before the call seems to resolve these problems.

Regards,

David

0 Kudos
Gerrit_V_1
Beginner
682 Views

Steve, many thanks for your advise. Indeed, In Compile the CPU was "Any CPU" and will follow your other advices..

The reason to use both Include file was that I (somehow) understood that combining them infact exclude the possible use of the build-in library  and I wanted to make sure of using the ISML libs as these were used in the former VB6 project (it looks to me as a negative times a negative, but being not convinced about it, I followed the suggestion).

Anyhow, my demo program is working perfectly, so now I can turn to my real project.

Again, many thanks.

Regards,

Gerrit Verboom

0 Kudos
Gerrit_V_1
Beginner
682 Views

David, thank for your remarks. You are ofcourse right. The Chr(0) was a left-over from a trial and I forgot to delete it. Removing it didn.t any harm to the working of the program. Removing the length parameter in the interface, as Steve suggested did the job.

Best regards,

Gerrit

 

0 Kudos
Steven_L_Intel1
Employee
682 Views

If you want IMSL to not use Intel MKL, then use just link_fnl_shared_imsl.h.

0 Kudos
Gerrit_V_1
Beginner
682 Views

Steve, I have implemented all your suggestions, i.e. remove the string length from the interface, add REFERENCE to STDCALL , removed the IMSL include file from source1 and set RB() to ByRef as this the only one to return data.

Clean the solution, save and start debugging. Result: exception "Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt."

Next I set RB() to ByVal. Result: same exception.

Finally, removed the REFERENCE (and let the statemen commented out in the code) and the other change the same, i.e. no string lengths, all data items ByVal. Result: perfekt.

It seems that arrays even when defined as ByVal return data to the UI.

I hope you have the time to look into this, although the question seems to be solved.

I attach the solution of the first run.

With kind regards,

Gerrit V. 

 

0 Kudos
Reply