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

Interface to C function

michael_green
Beginner
589 Views

Greetings,

I have acquired a third-party C function that I would like to use, but I can't get the linker to find it presumably because my interface is wrong - and it obviously is wrong too.

The start of the C function and its dummy arguments are:

#define PATH_MAX 200
#include <stdio.h>
#include <windows.h>
#include <shlobj.h>
#ifdef __cplusplus
extern "C" {
#endif
   int OpenAFolder(HWND hWnd, char dir_sel[PATH_MAX + 1], char *dir_org)
   {

and my attempt at an interface is:

interface
    logical*4 function OpenAFolder(hDlg,browsedFolderpath,initdir)
    !DEC$ ATTRIBUTES C	::	OpenAFolder
	
    integer(4)        hDlg 
    character(200)		browsedFolderpath,initdir

    !DEC$ ATTRIBUTES REFERENCE	::	hDlg,browsedFolderpath,initdir
	
    end function OpenAFolder
end interface

 

Would much appreciate some help in getting that interface right. Many thanks in advance.

Mike

0 Kudos
6 Replies
Arjen_Markus
Honored Contributor I
589 Views

I have not tested this, but I would use the modern Fortran binding features:

integer function OpenAFolder( hwnd, dir_sel, dir_org ) bind(C, name = "OpenAFolder")
     use, intrinsic :: iso_c_binding
     integer(kind=c_long), value :: hwnd
     character(len=1), dimension(*) :: dir_sel, dir_org
end function OpenAFolder

Note 1: from the C signature it is not clear whether dir_sel or dir_org are input-only or not. But in any case: the strings expected by the C routine are to be terminated with a NUL character - for your convenience c_null_char in ISO_C_BINDING.

Note 2: I am not entirely sure whether hwnd's kind should be c_long or c_long_long. It may be the latter.

0 Kudos
andrew_4619
Honored Contributor II
589 Views

hwnd is more likely type integer(c_intptr_t) for an integer address that will be 32 or 64 bit dependent on the application type and In would expect OpenAFolder to be integer(C_INT). Also see:

http://fortranwiki.org/fortran/show/iso_c_binding

0 Kudos
Arjen_Markus
Honored Contributor I
589 Views

Ah, you're right - I always overlook that one.

0 Kudos
michael_green
Beginner
589 Views

Thanks guys, that was just so easy.

How do you find out/learn how to do that stuff? All I have ever been able to do is to plagiarise other interfaces in an ad hoc manner, which doesn't facilitate true learning. Anything like an on-line tutorial somewhere?

Thanks again

Mike

0 Kudos
Arjen_Markus
Honored Contributor I
589 Views

For me it was the book by Metcalf, Reid and Cohen on Fortran 2003, but you could also have a look at the Fortran Wiki (http://fortranwiki.org/fortran/show/HomePage). Another valuable source of intormation is the comp.lang.fortran newsgroup.And then of course a strong incentive to learn the New Way was the mucking about with the Old Way for years - trying to get it all to work properly on different platforms evolved into a black art for me.

0 Kudos
Steve_Lionel
Honored Contributor III
589 Views

When I was porting Windows APIs to Fortran, I often had to go searching the Windows SDK for the definition of the typedefs used. Some of them are "obvious" (once you get the idea), such as HWND, others are more subtle. The Intel module IFWINTY can be helpful in identifying some of these, though all of the "handle to" typedefs are translated as INTEGER(HANDLE) in the modules.

As you have learned, you should not assume anything about which C type a typedef represents. If it is "long" in C, then C_LONG is fine, but if you don't know what HWND is, go look it up. Sometimes the answer is surprising.

0 Kudos
Reply