From: Dave Allured on
What is the best way to add a module interface to a predefined external
procedure, without changing the name of the procedure?

By "predefined" I mean to assume that the source code is unavailable,
such as in a precompiled library. I found a simple solution that
requires munging the original procedure name (as in mod1 below). This
is what I would like to fix.

Here is a cumbersome solution that uses two nested wrapper routines to
avoid the name conflict:

module mod1
subroutine vincent_x
call vincent ! this calls the external routine
end subroutine vincent_x
end module mod1

module mod2
subroutine vincent
use mod1
call vincent_x ! this calls the transitional routine
end subroutine vincent
end module mod2

Mod1 is the "transitional module", mod2 becomes the "public module" for
use by other programs.

Is there a more elegant way to preserve the original name that involves,
say, an interface block, or a single wrapper routine? If this was
previously discussed, a brief reference would be appreciated.

--Dave
From: Jim Xia on

You're talking about name mangling for module procedures ... You can
declare the external procedure in a module, and that'll prevent the
name being mangled.

module declarations
interface
subroutine vincent
end subroutine
end interface
end module

The the name vicent is visible to all users that USE declarations, and
the name is vincent, not mangled.

Hope this is what you're looking for.

Cheers,

Jim
From: Dave Allured on
Jim Xia wrote:
>
> You're talking about name mangling for module procedures ... You can
> declare the external procedure in a module, and that'll prevent the
> name being mangled.
>
> module declarations
> interface
> subroutine vincent
> end subroutine
> end interface
> end module
>
> The the name vicent is visible to all users that USE declarations, and
> the name is vincent, not mangled.
>
> Hope this is what you're looking for.

Close, thank you. I will give this a try. However I had in mind also
including the specs for procedure arguments and function results. I am
reaching for full interface checking at compile time.

Run time checking is not important to me right now, mostly because I
imagine it would be problematical, especially when the external routines
are not even fortran.

Expanding on yours, would this work, or what else would be needed?

module mod1
interface
integer function vincent (x)
real, intent(in) :: x
end function vincent
end interface
end module mod1

--Dave
From: Richard Maine on
Dave Allured <nospom(a)nospom.com> wrote:
> What is the best way to add a module interface to a predefined external
> procedure, without changing the name of the procedure?

and later added:

> Expanding on yours, would this work, or what else would be needed?
>
> module mod1
> interface
> integer function vincent (x)
> real, intent(in) :: x
> end function vincent
> end interface
> end module mod1

Yes. I'd have given basically the same answer as Jim, except with a
different emphasis. He seemed to be emphasizing the name mangling
issues, whereas I thought you were more talking about the explicit
interface issues. So I'll elaborate slightly on the explicit interafce
aspect.

I think that the term you are looking for is "explicit interface".
That's the general term for the property that allows various kinds of
argument checking, along with lots of other features new as of f90.
Module procedures do always have explicit interfaces, but that's not the
only way to have an explicit interface.

Yes, the way to get an explicit interface for an external procedure is
to write an interface body for it. Jim showed just the most trivial case
of an interface body - a subroutine with no arguments (probably because
that's what your original example showed). But the princinple applies to
any interface. Not only can you add the information about argument and
function return characteristics, you *MUST* do so. Your interface body
is required to agree with the actual procedure. You will not in general
get compile-time checking of that agreement; you have to get that part
right yourself. (There might be compilers that can do such checking, but
it isn't something that you can count on in general). But once you have
the interface body written, the compiler will check that the calls are
compatible with that interface.

You can put an interface block with its interface body directly in each
procedure that calls the external, possibly using an include file so
that you only have top get it right once. The other option is to put the
interface block in a module, as in the example above. Then you just USE
the module like any other (and you can take advantage of the rename
feature of USE, if that's part of what you want, though I didn't read
your question that way; I thought that you more wanted to avoid
renaming).

--
Richard Maine | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle | -- Mark Twain
From: Dave Allured on
Richard Maine wrote:
>
> Dave Allured <nospom(a)nospom.com> wrote:
> > What is the best way to add a module interface to a predefined external
> > procedure, without changing the name of the procedure?
>
> and later added:
>
> > Expanding on yours, would this work, or what else would be needed?
> >
> > module mod1
> > interface
> > integer function vincent (x)
> > real, intent(in) :: x
> > end function vincent
> > end interface
> > end module mod1
>
> Yes. I'd have given basically the same answer as Jim, except with a
> different emphasis. He seemed to be emphasizing the name mangling
> issues, whereas I thought you were more talking about the explicit
> interface issues. So I'll elaborate slightly on the explicit interafce
> aspect.
>
> I think that the term you are looking for is "explicit interface".
> That's the general term for the property that allows various kinds of
> argument checking, along with lots of other features new as of f90.
> Module procedures do always have explicit interfaces, but that's not the
> only way to have an explicit interface.
>
> Yes, the way to get an explicit interface for an external procedure is
> to write an interface body for it. Jim showed just the most trivial case
> of an interface body - a subroutine with no arguments (probably because
> that's what your original example showed). But the princinple applies to
> any interface. Not only can you add the information about argument and
> function return characteristics, you *MUST* do so. Your interface body
> is required to agree with the actual procedure. You will not in general
> get compile-time checking of that agreement; you have to get that part
> right yourself. (There might be compilers that can do such checking, but
> it isn't something that you can count on in general). But once you have
> the interface body written, the compiler will check that the calls are
> compatible with that interface.
>
> You can put an interface block with its interface body directly in each
> procedure that calls the external, possibly using an include file so
> that you only have top get it right once. The other option is to put the
> interface block in a module, as in the example above. Then you just USE
> the module like any other (and you can take advantage of the rename
> feature of USE, if that's part of what you want, though I didn't read
> your question that way; I thought that you more wanted to avoid
> renaming).

Great, this will work fine for my purposes. I really did mean to use
the term "module interface" because I want the end product to appear as
a single opaque module to application programs. I am trying to wrap a
third party library package in a module, replacing an include file with
a module interface, to improve interface checking.

I have a couple more questions. Consider this:

module mod1
integer, parameter :: XX_KIND = 4

interface
subroutine sub1 (arg1)
character(*), intent(in) :: arg1
end subroutine sub1

integer(XX_KIND) function func2 (arg2)
integer arg2
end function func2
end interface
end module mod1

1. What is the best way to make the kind definition of XX_KIND
available to the function statement for func2? Above does not seem to
work. I am reluctant to hard code "4" into each function statement.

2. Is it okay to use a single unnamed interface block to contain all of
my procedure interfaces, as shown? Or does each interface need its own
interface block? These are all 1 for 1 interfaces, no generic
interfaces.

--Dave