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

GUID

JohnNichols
Valued Contributor III
944 Views
Dear Steve:

In the WINDOWS API and using C there is a complicated procedure to create a GUID, but in FORTRAN it appears to be a bit simpler. Can you confirm that the following code creates GUID's for use in Fortran?

[bash]TYPE T_GUID
     SEQUENCE
       integer(ULONG) Data1 ! knowns  unsigned long 
       integer(USHORT) Data2 ! knowns  unsigned short 
       integer(USHORT) Data3 ! knowns  unsigned short 
!DEC$ IF DEFINED(__KEEP_OLD_CHARACTER_ARRAYS)
       character(UCHAR) Data4(8) ! knowns  unsigned char 
!DEC$ ELSE
       character(8) Data4
!DEC$ ENDIF
     END TYPE[/bash]
0 Kudos
8 Replies
Steven_L_Intel1
Employee
944 Views
"Fortran" doesn't know what a GUID is. You are creating a value that is passed to some procedure, most likely a Windows API routine. These typically want a 128 bit value. Many of the provided interfaces to these routines have arguments with a declared T_GUID type or something similar. You would need to look at the declaration of the routine to see which type it takes.

The declaration you post above, from IFWINTY, is a literal translation of a C declaration. It works, but is not necessarily the only way to create a GUID. The interesting part is that a GUID is usually represented as a 32-bit hex value, followed by three 16-bit hex values, followed by a 48-bit hex value. The type abpve doesn't really reflect that division, but as there are no 48-bit types in Fortran (or in C), it's as good a choice as any.

So that is the derived type structure. How you fill in the values is another thing, and yes, it can be messy. If I was doing this a lot I might write a function to do it to which I pass the usual string-form of a GUID.
0 Kudos
jimdempseyatthecove
Honored Contributor III
944 Views
The above is a data layout for the GUID not the generator.
See: http://en.wikipedia.org/wiki/Universally_unique_identifier
for some background information.
0 Kudos
JohnNichols
Valued Contributor III
944 Views
Dear Steve and Jim:

But my interest is only in two USB devices, both with unique GUID's that make a straigh declaration messy, but quick. At the moment I am just learning how to put it all together, so messy is fine. I think I have made a tolerable guess at the variable types and creating an interface to the SetupDiGetClassDevs, but when I link the linker can not find the SetupDiGetClassDevs in the SETUPAPI.lib. I included the library with the list of source files but this gives me a LNK2019 error. How do I link the lib in?

[bash]IntA = SetupDIGetClassDevs(USBOSR, Enums, hWNDP, INTD)[/bash]
0 Kudos
Steven_L_Intel1
Employee
944 Views
It's not "how do I link the lib in", but rather, "How do I declare this properly in Fortran? Looking at MSDN I'd guess it might be something like this:

[bash]interface
  function SetupDiGetClassDevs (ClassGUID, Enumerator, hwndParent, Flags)
  !DEC$ ATTRIBUTES STDCALL, DECORATE, ALIAS:"SetupDiGetClassDevs" :: SetupDiGetClassDevs
  use ifwinty
  integer(HANDLE) :: SetupDiGetClassDevs ! Function return value
  type (T_GUID), intent(in), optional :: ClassGUID
  !DEC$ ATTRIBUTES REFERENCE :: ClassGUID
  character(*), intent(in), optional :: Enumerator
  !DEC$ ATTRIBUTES REFERENCE :: Enumerator
  integer(HANDLE), intent(in), optional :: hwndParent
  integer(DWORD), intent(in) :: Flags
  end function SetupDiGetClassDevs
end interface[/bash]
0 Kudos
JohnNichols
Valued Contributor III
944 Views
Dear Steve:

I am having problem with the enumerator variable, the compiler does not like it, complains with a error #6832.

The other interesting feature is when I load the SLN file, MS Studio throws an exception message.

I enclose the entire directory as an attachment, as you might care to look at the exception message.

I am lost on the 6832 error.

I also got warnings on the optional flags, so I took them out.

Could you have a look at the program and tell me what mistake I ma making in trying to link to the C routine.

Thanks

JMN

0 Kudos
Steven_L_Intel1
Employee
944 Views
You cannot declare a local variable to be CHARACTER(*). You might choose CHARACTER(80) for EnumSA. But when MSDN says "set Enumerator to NULL" it doesn't mean the string "NULL" - it means the value NULL (0).

Yes, the OPTIONAL attributes I suggested don't work here. Use this instead:

[fortran]    interface
        function SetupDiGetClassDevs (ClassGUID, Enumerator, hwndParent, Flags)
            !DEC$ ATTRIBUTES STDCALL, DECORATE, ALIAS:"SetupDiGetClassDevs" :: SetupDiGetClassDevs
            use ifwinty
            integer(HANDLE) :: SetupDiGetClassDevs ! Function return value
            type (GUID), intent(in) :: ClassGUID
            !DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: ClassGUID
            character(*), intent(in):: Enumerator
            !DEC$ ATTRIBUTES REFERENCE, ALLOW_NULL :: Enumerator
            integer(HANDLE), intent(in) :: hwndParent
            !DEC$ ATTRIBUTES ALLOW_NULL :: hwndParent
            integer(DWORD), intent(in) :: Flags
        end function SetupDiGetClassDevs
    end interface[/fortran]
and change the call to:

IntA = SetupDIGetClassDevs(USBOSR, NULL, NULL, INTD)

See how that works for you.
0 Kudos
JohnNichols
Valued Contributor III
944 Views
Steve:

No that did not fix it, I dug out my Fortran 95/2003 Explained Book from my bookcase, the bookcasenearest the beer and my comfortable chair. Anne only lets me keep a few books beside the comfy chair.

The C Routine has the first argument as a C pointer to the GUID, as far as my limited understanding of interfaces goes we are actually passing or attempting to pass the type(GUID), do we not need a pointer to a GUID, a c_ptr type?

Now that is way beyond anything I have done before.

Just a thought.

JMN
0 Kudos
Steven_L_Intel1
Employee
944 Views
No, the interface I provided has the GUID passed by reference, which is what it wants.
0 Kudos
Reply