Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
Announcements
FPGA community forums and blogs on community.intel.com are migrating to the new Altera Community and are read-only. For urgent support needs during this transition, please visit the FPGA Design Resources page or contact an Altera Authorized Distributor.
29280 Discussions

Passing strings back to VB2005 caller from IVF dll

Al_Worth
Beginner
1,215 Views

There have been several threads in this forum about passing strings (usually file paths for read operations) from VB2005 to a .dll written in IVF. These were very helpful to me in trying to do th same thing. After I got that working, I attempted to pass a string that was read from the file along with a bunch of numeric data back to the VB calling routine with no success at all.

The closest I came was being able to see the string in the dll code after setting a breakpoint just before the dll returned.

I have attached a file with some code snippets and comments and would be very grateful for any pointers.

As an aside, I'd like to mention that on the way to getting the file pathname string from VB to IVF I learned that you can't be cavalier about the ansi/unicode/auto attribute in the VB delare statement, no matter how enticing the term "AUTO" may sound. It needs to be "ansi" or nothing at all since "ansi" is the default. If you use AUTO or UNICODE without (I suppose) additional programming details you will get a few characters of gibberish instead of your string, even if all the other code is OK.

0 Kudos
9 Replies
Steven_L_Intel1
Employee
1,215 Views

I have not looked at your code, but I would strongly recommend using the "BSTR" routines to send strings back to VB. I don't think you can do it with normal Fortran code. See one of the provided VB-calling-Fortran samples for details.

0 Kudos
Al_Worth
Beginner
1,215 Views

I have not looked at your code, but I would strongly recommend using the "BSTR" routines to send strings back to VB. I don't think you can do it with normal Fortran code. See one of the provided VB-calling-Fortran samples for details.

I started researching "BSTR" routines based on your suggestion and didn't find much in the IVF or MS VS2005 help info. I also downloaded the IVF 11.066 trial version to look at the mixed programming samples, but the ones I found didn't provide much help. I did find out that VB and the CLR of .NET really doesn't want you messing with it's strings. I also discovered the existence of "stringbuilder", but haven't figured out how to use it yet.

I know I'm going to have to get up to speed on this eventually, but for my present situation I only need to return a single 48 character string to the VB caller. I found that a byte array with appropriate glue code in the caller and the subroutine does the job quite well.

For future reference, I'd be delighted for any links and/or pointers to good intro material on passing strings to managed code.

Thanks very much.

0 Kudos
Steven_L_Intel1
Employee
1,215 Views

Look at the VB.NET-Safearrays sample for an example of using BSTR. You can find documentation of the Fortran-provided routines for manipulating BSTRs, such as ConvertBSTRToString, in the compiler docs.

0 Kudos
anthonyrichards
New Contributor III
1,215 Views

Look at the VB.NET-Safearrays sample for an example of using BSTR. You can find documentation of the Fortran-provided routines for manipulating BSTRs, such as ConvertBSTRToString, in the compiler docs.

In the compiler INCLUDE files you should be able to find a reference to a Bitstring data type, such As

TYPE T_SAFEARR_BSTR
SEQUENCE
integer(ULONG) Size ! knowns ULONG
integer(LPVOID) aBstr ! star wireBSTR *
END TYPE

If you USE the appropriate module (DFWINTY in my case, as I use Compaq Visual Fortran) you will find it and you can then define a bitstring-type for use in returning your string to VBasic.

Suppose the type is defined thus:
TYPE T_SAFEARR_BSTR
SEQUENCE
integer(ULONG) Size ! knowns ULONG
integer(LPVOID) aBstr ! star wireBSTR *
END TYPE

Then the following code may work:

Type (T_SAFEARR_BSTR) MyBitString
Character(100) MyString

MyString="This is my null-terminated character string"//CHAR(0)
MyBitString%Size=LEN_TRIM(MyString)
MyBitSTring%aBstr=LOC(MyString)

You should therefore provide an INTENT(OUT) argument for the Bit-string to be returned to VBasic.
As Steve pointed out, you could also define a VARIANT and make it a Bit-String Type and return that.
(On further reading, I think there may be issues regarding freeing the memory allocation for the string when it is no longer neededon the VBasic side,whichmay only be solved by using SysAllocString to populate the Bit String structure. This latter function returns a pointer to the Bit-string it populates. The memory can then be freed by using SysFreeString function)

0 Kudos
Al_Worth
Beginner
1,215 Views
Thanks to both of you, Steve and Anthony. I now have some solid leads to follow up, which should provide plenty of recreation for several days to come! I guess I blewby the example too quickly, because I didn't notice it.
Thanks again for your help.

0 Kudos
anthonyrichards
New Contributor III
1,215 Views
I have spent some time on this and now have a VB6 project that can send a character string to Fortran using one call and that can get a string from Fortran using another call. If you want toget string from Fortran to VB, then you first have to define a buffer in VB to take the string. You then have to send Fortran a pointer to the string part and an integer value that gives the length of the buffer. This is done by specifying ByRef for the string argument. VB automatically converts strings from its internal unicode character (2 bytes per character)representation to ASCII (1 byte per character) when sending and receiving strings to/from external code (code indicated by the use of 'Declare' in the VB code), so you do not have to worry about converting backwards and forwards between Unicode and ASCII.
I have packaged up the VB project into the attached Zip. I include the two Fortran files which I used as the basis of two DLL's (one called FCall.dll which contains the SENDFOTRANSTRING subroutine and the other called FCALL2.DLL which contains the GETFORTRANSTRING function). I also include, inside a MS WORD document,screenshots showing the VB project and a debug view of each Fortran DLL project so that you can see the contents of addresses, argument values etc when the Fortran code is executed in debug mode.
One important caveat: I use Compaq Visual Fortran, which I believe assumes STDCALL for exported/imported functions/routines. This matches the default STDCALL used by Visual Basic. If you use IVF, I believe that it may not use STDCALL by default, so you may need to specify STDCALL explicitly to get the code to work for you. Steve will let you know about this wrinkle.
Regarding general information on how to pass arrays and strings between VB and Fortran I can point you to the following useful linkwhere, although spcifically dealing with VB calling C and C++, much of its advice is applicable to calling Fortran as well.

0 Kudos
rbhuff
Beginner
1,215 Views
Quoting - anthonyrichards
I have spent some time on this and now have a VB6 project that can send a character string to Fortran using one call and that can get a string from Fortran using another call. If you want toget string from Fortran to VB, then you first have to define a buffer in VB to take the string. You then have to send Fortran a pointer to the string part and an integer value that gives the length of the buffer. This is done by specifying ByRef for the string argument. VB automatically converts strings from its internal unicode character (2 bytes per character)representation to ASCII (1 byte per character) when sending and receiving strings to/from external code (code indicated by the use of 'Declare' in the VB code), so you do not have to worry about converting backwards and forwards between Unicode and ASCII.
I have packaged up the VB project into the attached Zip. I include the two Fortran files which I used as the basis of two DLL's (one called FCall.dll which contains the SENDFOTRANSTRING subroutine and the other called FCALL2.DLL which contains the GETFORTRANSTRING function). I also include, inside a MS WORD document,screenshots showing the VB project and a debug view of each Fortran DLL project so that you can see the contents of addresses, argument values etc when the Fortran code is executed in debug mode.
One important caveat: I use Compaq Visual Fortran, which I believe assumes STDCALL for exported/imported functions/routines. This matches the default STDCALL used by Visual Basic. If you use IVF, I believe that it may not use STDCALL by default, so you may need to specify STDCALL explicitly to get the code to work for you. Steve will let you know about this wrinkle.
Regarding general information on how to pass arrays and strings between VB and Fortran I can point you to the following useful linkwhere, although spcifically dealing with VB calling C and C++, much of its advice is applicable to calling Fortran as well.


0 Kudos
rbhuff
Beginner
1,215 Views

Sorry for the empty post. I am having difficulty downloading your attachment (vbcallsfortran.zip). I keep getting a blank download page. Would you mind adding the file again? Thanks in advance.


0 Kudos
Steven_L_Intel1
Employee
1,215 Views
The blank page is a forum bug that is being worked on. Sorry for the inconvenience.
0 Kudos
Reply