- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Visual Studio 2010 seems to recognize it as C code, the text colors are correct and the icon in the file view tree shows it as a C program. However it does not seem to compile. I did buy the VS 2010 and Help/About does show the C++ compiler.
Do I need a custom build step and what is that?
Or is there another way to convert between IEEE and the old IBM floating point formats?
Thanks,
Charles
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Microsoft no longer supports mixed-language projects, so the way you have to do this now is create a Solution with two projects, one for your C code and one for your Fortran code. Whichever is the main program should be an executable project and the other a static library project. Use the Project > Dependences menu to make the library a dependent of the executable. See also configuring Visual C++ for mixed-language applications.
Take a look at the mixed-language samples provided.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The "configuring Visual C++ for mixed-language applications" actually addresses Fortran libraries with C++ main programs, which is different from what I am trying to do. I have a C code of several lines containing two functions. I tried to create a project, but I cannot seem to find anything that looks like creating a C language static library, which is what I think I want. I see that for Fortran, but not for C. What kind of project do I need?
Too bad Microsoft abandonded the mixed language programming. Maybe they got too many languages and couldn't manage it anymore.
Thanks in advance,
Charles
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If there is name mismatch and the linker cannot find the C-functions/routines, do a DUMPBIN on the C .OBJ file to list the symbol table and see what the C routines are called and then match up your Fortran calls to reference the same names using the ALIAS atribute and to match the calling convention used by the C code. In order to do this, you will need to generate an interface block for your C functions/subroutines for use in your Fortran to let the Fortran compiler know what it is to expect (ALIAS and calling convention) when you reference a C function/routine that is to be linked from your C .OBJ file.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Microsoft never released a "Visual Studio 2000". It went from '98 to 2002.
To create a C static library project, use the Win32 project type and then the "Win32 Project" template. There you can select a static library. You will want to ensure that the run-time library settings are the same in the C and Fortran projects. In C/C++, this is under Code Generation.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Microsoft never released a "Visual Studio 2000". It went from '98 to 2002.
Sorry, the real name seems to be Visual Studio 6.0 Enterprise Edition.
To create a C static library project, use the Win32 project type and then the "Win32 Project" template. There you can select a static library. You will want to ensure that the run-time library settings are the same in the C and Fortran projects. In C/C++, this is under Code Generation.
Sorry, the real name seems to be Visual Studio 6.0 Enterprise Edition.
OK, I decided to try to go the way of including the obj file rather than creating a library for a single module, but I am still having problems with this and alsowith a library I am trying to use. Fortran looks for "_FLOATTOIBM" whereas OBJ compiled from the VS 2010 C++ compiler is called "FLOATTOIBM@16". I can add the underscore and then it is called "_FLOATTOIBM@16" and it is still not recognized. If I use the OBJ compiled with Visual C++ 6.0, it doesn't work either, it also has the @ 16.
For the library, the symbol searched for in the Fortran is "_KECHK32" but the lib file (I am trying to import from a DLL eventually) calls it "_KECHK32@4".
I am getting this information by looking at the obj or lib files with a HEX editor.
Going back to the CVF code, the "@16" is present in both calling and called OBJ files. I remember if you called a routine in CVF with the right name but wrong number of arguments, it would complain about not finding "SUB@32" or whatever. So the IVF does not differentiate on number of arguments?
The really important thing is the library DLL import. The C code can probably be implemented in Fortran if this turns out to be a nightmare, but there must be some way to call C from Fortran. I did look at the C compiler options and selected STD_CALL, which was not originally selected, but this did not help.
So it really seems to be the lack of the @ sign and the byte count of the argument list that is the problem.
I tried the !$DEC ALIAS FLOATTOIBM FLOATTOIBM@16 statement and that did not help either.
Any suggestions appreciated.
Thanks,
Charles
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The C-function that converts a 32-bit IBM 360 float, passed as a 32-bit word, returning a double:
[cpp]#includeThe Fortran main program, which calls the C function using F2003 C-interoperability, and the example from http://en.wikipedia.org/wiki/IBM_Floating_Point_Architecture:
#include
struct ibm32{
unsigned frac : 24;
unsigned biasexp : 7;
unsigned s : 1;
};
double ibm2dble(struct ibm32 w){
double absval=ldexp((double)w.frac,4*(w.biasexp-64)-24);
printf(" IBM FLOAT FRAC = %08Xn IBM FLOAT EXPO = %08Xn IBM FLOAT SIGN = %1Xn",
w.frac,w.biasexp,w.s);
return w.s ? -absval : + absval;
}
/*
#include
union ibm32u{
struct ibm32 w;
long l;
};
main(){
union ibm32u uw;
uw.l=0xC276A000;
printf("%22.15e",ibm2float(uw.w));
}
*/
[/cpp]
[fortran]program ibm2ieeeCompile the C function to an .OBJ file, and compile the Fortran code to an .EXE:
use iso_c_binding
interface
real(c_double) function ibm2dble(l) bind(C)
use iso_c_binding
integer(c_int32_t), value :: l
end function ibm2dble
end interface
integer(c_int32_t) :: l=Z'C276A000';
write(*,*)' Decimal value of IBM FLOAT word = ',ibm2dble(l)
end program ibm2ieee
[/fortran]
[bash]s:LANG:> cl /MD /c ibm32.cRun the program and compare the result to that in the Wikipedia article:
s:LANG:> ifort /MD ibmdbl.f90 ibm32.obj
[/bash]
[bash]s:LANG>ibmdbl
IBM FLOAT FRAC = 0076A000
IBM FLOAT EXPO = 00000042
IBM FLOAT SIGN = 1
Decimal value of IBM FLOAT word = -118.625000000000
[/bash]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Steve and Mecej4,
I was afraid there would not be good news.
I am sure I can find a way to recompile my C code to get it to work with IVF. Or find another way to convert between (I need to go both ways) IEEE and IBM float (single precision only).
But I do have an antique library (or did you say "ancient") for which I may not be able to get a modern replacement. This is the copy protection dongle interface and means I either stay in CVF for existing products or ask people all over the world to exchange keys for new ones at substantial expense to either me or them.
As you know, staying in CVF means nursing Win XP machines for the duration...
So, can I use the Interface
interface
double precision function ibm2dble(l) bind(C)
use iso_c_binding
integer,value :: l
end function ibm2dble
end interface
in some way to link with the existing KECHK32@4? If so, what binding would I use? STDCALL?
Are there examples of this?
Thanks,
Charles
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You should read about and understand this point about C-interoperability from the standpoint of the Fortran standard:
it is a specification to follow with a definite pair of C and Fortran "processors", i.e., compilers, with guaranteed success, at least as to interoperability.
Intel Fortran and MSVC (or Intel C) are one such pair; GFortran and GCC are another such pair. On the other hand, it is almost possible to guarantee that an arbitrary pair, e.g., IFort and GCC or Absoft Fortran and ICC, will not work.
Typically, the C compiler of the defined pair knows nothing about and does not care about being called from or calling into Fortran -- there is no Fortran Interoperability section in the C standards. Therefore, the Fortran compiler in the defined pair has to produce .OBJ files that are suitable for linking with the C .OBJ files. Given the diversity of calling and name decoration conventions, it is understandable that there is only one specified compatible C compiler -- it is called the "Companion Processor" in the Fortran standards.
Similar comments can be made about compiler options such as /Gm and /iface:xxx. Typically, explicitly declared attributes such as _cdecl or _stdcall override compiler options. Neither the Fortran nor the C compiler does anything to confirm whether the other compiler was used with those options that are essential for interoperability; doing so falls on the the shouders of the programmer.
We do not know what the contents of this ancient library of yours are, beyond the IEEE <--> IBM-360 floating point conversions. Chances are very good that you can assemble a new library from pieces available freely. Just as 16-bit code no longer runs on W7, your old library will become unusable one of these days.
By the way, CVF 6.6 works fine in command-line mode on W7-X64. It is the GUI and installers that fail.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Your attempt at using the 'ALIAS' attribute looks wrong.
It should be along the lines of the following (the @16 implies FOUR arguments are required). I'll assume that
it is a subroutine you are calling (just swap REAL(4) FUNCTION - or whatever type - for SUBROUTINE and END FUNCTION for END SUBROUTINE if it is a function call)
INTERFACE
Subroutine FLOATTOIBM(arg1,arg2,arg3,arg4)
!DEC$ ATTRIBUTES STDCALL, ALIAS:'_FLOATTOIBM@16' :: FLOATTOIBM
!DEC$ ATTRIBUTES REFERENCE :: arg1
!DEC$ ATTRIBUTES REFERENCE :: arg2
!DEC$ ATTRIBUTES REFERENCE :: arg3
!DEC$ ATTRIBUTES REFERENCE :: arg4
!Correctly define the argument types here...for example
REAL(4) arg1,arg2
INTEGER(4) arg3,arg4
END SUBROUTINE FLOATTOIBM
END INTERFACE
The 'ALIAS' specifies that the aliased name for the (automatic) uppercase Fortran name 'FLOATTOIBM' is '_FLOATTOIBM@16', and this is the name to be searched for when linking. It is important that the ALIAS anem agrees with the case of the symbol name in the C- object file, in ALL details.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1. If you can call something from CVF you can call it from Intel Visual Fortran. Period. At most you may need to construct a proper INTERFACE block.
2. The major change in calling between CVF and IVF is the default calling convention. CVF used STDCALL with string lengths immediately following the string address in the argument list, IVF uses C and puts the string lengths at the end. Both compilers have directives and options to do it the "other" way.
3. You should (almost) never add the @n suffix in an ALIAS. This is why we invented the DECORATE attribute. So looking at Anthony's example, one might write:
!DEC$ ATTRIBUTES STDCALL, REFERENCE, DECORATE, ALIAS:"FLOATTOIBM" :: FLOATTOIBM
The compiler will add the correct decoration, including leading underscore and trailing @n. Note that these naming conventions are different when building for x64 - the compiler will do the right thing.
4. Microsoft did not change calling conventions - the Win32 API as well as the interpretive languages use STDCALL almost exclusively, but the MS C compiler defaults to the C mechanism. If you want to call a STDCALL routine from C you need to add __stdcall to the routine header.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think if I can figure out how to get IBMtoFloat to work, I can get the key interface software to work.
I have never used any of this interface stuff, so this is new to me.
Again, I have source for the IBMtoFloat, so I am not stuck there, it is with the ancient library for which I have no source that is the problem.
I will come back and let you know if I get it to work.
BTW, here is the code for the IBM/IEEE code FYI
Charles
/* Assumes sizeof(int) == 4 */
extern void __stdcall _FLOATTOIBM(int from[], int to[], int n, int endian)
/**********************************************************************
float_to_ibm - convert between 32 bit IBM and IEEE floating numbers
***********************************************************************
Input:
from input vector
n number of floats in vectors
endian =0 for little endian machine, =1 for big endian machines
Output:
to output vector, can be same as input vector
***********************************************************************
Notes:
Up to 3 bits lost on IEEE -> IBM
IBM -> IEEE may overflow or underflow, taken care of by
substituting large number or zero
Only integer shifting and masking are used.
***********************************************************************
Credits: CWP: Brian Sumner
***********************************************************************/
{
register int fconv, fmant, i, t;
for (i=0;i
fconv = from;
if (fconv) {
fmant = (0x007fffff & fconv) | 0x00800000;
t = (int) ((0x7f800000 & fconv) >> 23) - 126;
while (t & 0x3) { ++t; fmant >>= 1; }
fconv = (0x80000000 & fconv) | (((t>>2) + 64) << 24) | fmant;
if(endian==0)
fconv = (fconv<<24) | ((fconv>>24)&0xff) |
((fconv&0xff00)<<8) | ((fconv&0xff0000)>>8);
}
to = fconv;
}
return;
}
extern void __stdcall _IBMTOFLOAT(int from[], int to[], int n, int endian)
/***********************************************************************
ibm_to_float - convert between 32 bit IBM and IEEE floating numbers
************************************************************************
Input::
from input vector
to output vector, can be same as input vector
endian byte order =0 little endian (DEC, PC's)
=1 other systems
*************************************************************************
Notes:
Up to 3 bits lost on IEEE -> IBM
Assumes sizeof(int) == 4
IBM -> IEEE may overflow or underflow, taken care of by
substituting large number or zero
Only integer shifting and masking are used.
*************************************************************************
Credits: CWP: Brian Sumner, c.1985
*************************************************************************/
{
register int fconv, fmant, i, t;
for (i=0;i
fconv = from;
if (fconv) {
/* if little endian, i.e. endian=0 do this */
if (endian==0) fconv = (fconv<<24) | ((fconv>>24)&0xff) |
((fconv&0xff00)<<8) | ((fconv&0xff0000)>>8);
fmant = 0x00ffffff & fconv;
if(fmant){
t = (int) ((0x7f000000 & fconv) >> 22) - 130;
while (!(fmant & 0x00800000)) { --t; fmant <<= 1; }
if (t > 254) fconv = (0x80000000 & fconv) | 0x7f7fffff;
else if (t <= 0) fconv = 0;
else fconv = (0x80000000 & fconv) |(t << 23)|(0x007fffff & fmant);
}
else fconv=0;
}
to = fconv;
}
return;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
For the C obj file (posted earlier) I used
INTERFACE
Subroutine FLOATTOIBM(arg1,arg2,arg3,arg4)
!DEC$ ATTRIBUTES STDCALL, DECORATE, ALIAS:"FLOATTOIBM" :: FLOATTOIBM
!DEC$ ATTRIBUTES REFERENCE :: arg1
!DEC$ ATTRIBUTES REFERENCE :: arg2
!DEC$ ATTRIBUTES VALUE :: arg3
!DEC$ ATTRIBUTES VALUE :: arg4
!Correctly define the argument types here...
REAL(4) arg1(:),arg2(:)
INTEGER(4) arg3,arg4
END SUBROUTINE FLOATTOIBM
END INTERFACE
Calling with
CALL FloatToIbm(SR%TRACES(1:SR%NSAMP,I),TRACE,%VAL(SR%NSAMP),%VAL(0))
and for the imported DLL, I used
INTERFACE
Subroutine KECHK32(arg1)
!DEC$ ATTRIBUTES DLLIMPORT :: KECHK32
!DEC$ ATTRIBUTES STDCALL, DECORATE, ALIAS:"KECHK32" :: KECHK32
!DEC$ ATTRIBUTES REFERENCE :: arg1
!Correctly define the argument types here...
TYPE SCB ! 80 bytes total., ALIAS:'_KECHK32'
SEQUENCE
INTEGER*2 err_code ! 000 Error Code1.
INTEGER*2 err_status1 ! 002 Error Status 1.
INTEGER*2 err_status2 ! 004 Error Status 2.
CHARACTER*1 func_code ! 006 Function Code.
CHARACTER*5 scb_id ! 007 SCB Identification, s/b "..?Z".
CHARACTER*9 prod_name ! 012 Product Name (ASCIIZ).
CHARACTER*3 reserved1 ! 021 Reserved.
INTEGER*4 prod_serial ! 024 Product Serial Number.
INTEGER*4 pin ! 028 Product ID Number (PIN).
INTEGER*2 ecl ! 032 Exec-Count Limit (ECL).
INTEGER*2 edl ! 034 Expire-Days Limit (EDL).
CHARACTER*9 expire_date ! 036 Expire-Date (ED) (ASCIIZ).
CHARACTER*16 user_data ! 045 User-Data.
CHARACTER*6 rom_serial ! 061 Device ROM Serial#.
CHARACTER*8 lasered_id ! 067 Device Lasered-ID (LID).
CHARACTER*5 reserved2 ! 075 Reserved.
END TYPE SCB
TYPE (SCB) arg1
END SUBROUTINE KECHK32
END INTERFACE
Calling with
CALL KECHK32(AZBLOCK)
Thanks again,
Charles

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