Home > Archive > Fortran > March 2006 > Character String Dynamic Allocation
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Character String Dynamic Allocation
|
|
| gary.l.scott@lmco.com 2006-03-24, 7:07 pm |
| Hi,
A rich text entry field can be set to limit the number of characters
typed by a user, however if OLE objects are allowed to be pasted to the
field, it can exceed the size of a statically allocated string assigned
to retrieve the final edited content. The particular third party API
being used requires a string, not an array. Since you can't
dynamically allocate a string in F95 (so that I can size it to fit the
actual rich text content after the user finishes editing), is there a
way to allocate a character(len=1) array and type cheat (equivalence,
integer pointers) (or other method)? Both approaches failed but I fear
that there's something I'm overlooking.
| |
| robert.corbett@sun.com 2006-03-24, 10:00 pm |
|
gary.l.scott@lmco.com wrote:
> Hi,
>
> A rich text entry field can be set to limit the number of characters
> typed by a user, however if OLE objects are allowed to be pasted to the
> field, it can exceed the size of a statically allocated string assigned
> to retrieve the final edited content. The particular third party API
> being used requires a string, not an array. Since you can't
> dynamically allocate a string in F95 (so that I can size it to fit the
> actual rich text content after the user finishes editing), is there a
> way to allocate a character(len=1) array and type cheat (equivalence,
> integer pointers) (or other method)? Both approaches failed but I fear
> that there's something I'm overlooking.
I don't understand what you mean. Doesn't the following program
dynamically allocate a string?
FUNCTION ASTRING(N)
POINTER ASTRING
CHARACTER*(N) ASTRING
ALLOCATE (ASTRING)
END
SUBROUTINE SUBR(N)
INTERFACE
FUNCTION ASTRING(N)
POINTER ASTRING
CHARACTER*(N) ASTRING
END FUNCTION
END INTERFACE
CHARACTER*(N), POINTER :: PSTRING
PSTRING => ASTRING(N)
PSTRING = REPEAT('A', N)
PRINT *, PSTRING
END
PROGRAM MAIN
READ *, N
CALL SUBR(N)
END
Bob Corbett
| |
| Gary L. Scott 2006-03-25, 4:00 am |
| robert.corbett@sun.com wrote:
> gary.l.scott@lmco.com wrote:
>
>
>
> I don't understand what you mean. Doesn't the following program
> dynamically allocate a string?
>
> FUNCTION ASTRING(N)
> POINTER ASTRING
> CHARACTER*(N) ASTRING
> ALLOCATE (ASTRING)
> END
>
> SUBROUTINE SUBR(N)
> INTERFACE
> FUNCTION ASTRING(N)
> POINTER ASTRING
> CHARACTER*(N) ASTRING
> END FUNCTION
> END INTERFACE
>
> CHARACTER*(N), POINTER :: PSTRING
> PSTRING => ASTRING(N)
> PSTRING = REPEAT('A', N)
> PRINT *, PSTRING
> END
>
> PROGRAM MAIN
> READ *, N
> CALL SUBR(N)
> END
>
> Bob Corbett
>
Seems to work. Thanks. I was declaring the string with the
"allocatable" attribute which didn't work. I missed something somewhere
apparently.
--
Gary Scott
mailto:garyscott@ev1.net
Fortran Library: http://www.fortranlib.com
Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html
Why are there two? God only knows.
If you want to do the impossible, don't hire an expert because he knows
it can't be done.
-- Henry Ford
| |
| robert.corbett@sun.com 2006-03-25, 4:00 am |
|
Gary L. Scott wrote:
> Seems to work. Thanks. I was declaring the string with the
> "allocatable" attribute which didn't work. I missed something somewhere
> apparently.
Fortran 95 does not allow scalars to have the ALLOCATABLE
attribute. Fortran 2003 does.
Bob Corbett
| |
| Gary L. Scott 2006-03-25, 7:01 pm |
| robert.corbett@sun.com wrote:
> Gary L. Scott wrote:
>
>
>
>
> Fortran 95 does not allow scalars to have the ALLOCATABLE
> attribute. Fortran 2003 does.
>
> Bob Corbett
>
Since the API call is in the program main and "An automatic object is
invalid in a main program.", I guess that means I must make a wrapper
for the 3rd party API which is already a wrapper for a wrapper. Sheesh,
what a kludge.
--
Gary Scott
mailto:garyscott@ev1.net
Fortran Library: http://www.fortranlib.com
Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html
Why are there two? God only knows.
If you want to do the impossible, don't hire an expert because he knows
it can't be done.
-- Henry Ford
| |
| Gary L. Scott 2006-03-25, 7:01 pm |
| Gary L. Scott wrote:
> robert.corbett@sun.com wrote:
>
> Since the API call is in the program main and "An automatic object is
> invalid in a main program.", I guess that means I must make a wrapper
> for the 3rd party API which is already a wrapper for a wrapper. Sheesh,
> what a kludge.
>
Here is a tentative solution. It is VERY scary. Since I need access to
the storage in the main, this works. The scary part is that I can
access beyond the allocated size because string length intrinsics are
unaware. I must be careful to pass an explicit length or substring.
Given the requirement to access the storage in the program main, what
other solution is there?
!
! A test program
!
module string
contains
function aString(N)
implicit none
integer :: n
character(n), pointer :: aString
allocate(aString)
end function
end module
program test
use string
implicit none
integer :: n
character(2147483647), pointer :: pString !Maximum possible size of
rich edit field
open(10,file="c:\data.txt")
!
! Value of N would be determined by query of rich edit field via 3rd
party API
!
n=22
pString => aString(N)
pString(1:n) = "0233456709101112131415"
write(10,'(a,a)')'pString=',pString(1:n)
call ThirdPartyAPI(pString(1:n))
end program
subroutine ThirdPartyAPI(charval)
implicit none
character(*) :: charval
write(10,'(a,i0)')'ArgLen=',len(charval)
return
end subroutine
--
Gary Scott
mailto:garyscott@ev1.net
Fortran Library: http://www.fortranlib.com
Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html
Why are there two? God only knows.
If you want to do the impossible, don't hire an expert because he knows
it can't be done.
-- Henry Ford
| |
|
| well, it is not standard Fortran, because :
pString => aString(N)
is only allowed if pString and aString have the same LEN (and they have
not except for N=...)
Joost
| |
| Brooks Moses 2006-03-25, 7:01 pm |
| Gary L. Scott wrote:
> Gary L. Scott wrote:
>
> Here is a tentative solution. It is VERY scary. Since I need access to
> the storage in the main, this works. The scary part is that I can
> access beyond the allocated size because string length intrinsics are
> unaware. I must be careful to pass an explicit length or substring.
> Given the requirement to access the storage in the program main, what
> other solution is there?
Another solution might be to write a wrapper that uses an automatic
string to get the data and then copies it into something like an
ISO_VARYING_STRING representation (which is, underneath, essentially the
allocatable array of characters that you were looking for, but with all
the tricky bits already done for you), and passes the latter back to main.
- Brooks
--
The "bmoses-nospam" address is valid; no unmunging needed.
| |
| Gary L. Scott 2006-03-25, 7:01 pm |
| Joost wrote:
> well, it is not standard Fortran, because :
>
> pString => aString(N)
>
> is only allowed if pString and aString have the same LEN (and they have
> not except for N=...)
>
> Joost
>
But that's the whole point isn't it? I don't know what the length will
be in the main but I have to declare the pointer somehow if I want to
pass it directly to those procedures called in main. I can't use an
'automatic' method in main.
This works ok with the compiler I'm using so it will likely be my near
term solution until I figure out a better way (hopefully one that works
with the string length intrinsics and one that doesn't involve hiding
the third party API behind a bunch of new wrappers). Once I decide how
many or few APIs are impacted, I may give in and hide it behind wrappers
with some extra length checking for safety.
--
Gary Scott
mailto:garyscott@ev1.net
Fortran Library: http://www.fortranlib.com
Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html
Why are there two? God only knows.
If you want to do the impossible, don't hire an expert because he knows
it can't be done.
-- Henry Ford
| |
| Gary L. Scott 2006-03-25, 7:01 pm |
| Brooks Moses wrote:
> Gary L. Scott wrote:
>
>
>
> Another solution might be to write a wrapper that uses an automatic
> string to get the data and then copies it into something like an
> ISO_VARYING_STRING representation (which is, underneath, essentially the
> allocatable array of characters that you were looking for,
Allocatable array of characters? I don't quite follow. I can allocate
a character(1) array using standard methods with F95. But the API
expects a scalar string.
> but with all
> the tricky bits already done for you), and passes the latter back to main.
It passes it back as a fixed length string? (I've never used the varying
string module,
but I should probably study it in relation to this problem).
>
> - Brooks
>
>
--
Gary Scott
mailto:garyscott@ev1.net
Fortran Library: http://www.fortranlib.com
Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html
Why are there two? God only knows.
If you want to do the impossible, don't hire an expert because he knows
it can't be done.
-- Henry Ford
| |
| Brooks Moses 2006-03-25, 10:00 pm |
| Gary L. Scott wrote:
> Brooks Moses wrote:
>
> Allocatable array of characters? I don't quite follow. I can allocate
> a character(1) array using standard methods with F95. But the API
> expects a scalar string.
I think I probably the issue a bit. There are two independent
pieces to my proposed solution. One of them (which has nothing to do
with ISO_VARYING_STRING) is the wrapper function that passes a scalar
string to the API, and returns a character(1) array. Here's some
Fortranlike pseudocode for that, which will hopefully explain this a lot
more clearly:
program main
character(1), allocatable, dimension(:) :: thedata
len = getStringLengthFromAPI()
allocate(thedata(len))
call wrapperFunction(thedata, len)
! Other things happen with thedata here in the main program.
contains
subroutine wrapperFunction(thedata, len)
character(1), dimension(:) :: thedata
character(len) :: internalstring
call getStringFromAPI(internalstring)
! The following line needs some cleverness added....
thedata = internalstring
end subroutine
end
Similarly, any other cases where you're calling something on thedata
that expects a scalar string can use the same sort of wrappers.
>
> It passes it back as a fixed length string? (I've never used the varying
> string module,
> but I should probably study it in relation to this problem).
The second part of what I'm suggesting is a further modification of the
above pseudocode, implementing thedata as an ISO_VARYING_STRING rather
than an array of character(1) as I've shown it.
It won't do anything magical to fix the overall problem, as far as I
know (I haven't looked at it too closely either), but it should make
things like the "thedata = internalstring" operation easier, in that you
won't have to implement your own loop over all the characters in the
string for that.
- Brooks
--
The "bmoses-nospam" address is valid; no unmunging needed.
| |
| Gary L. Scott 2006-03-25, 10:00 pm |
| Brooks Moses wrote:
> Gary L. Scott wrote:
>
>
>
> I think I probably the issue a bit. There are two independent
> pieces to my proposed solution. One of them (which has nothing to do
> with ISO_VARYING_STRING) is the wrapper function that passes a scalar
> string to the API, and returns a character(1) array. Here's some
> Fortranlike pseudocode for that, which will hopefully explain this a lot
> more clearly:
>
> program main
> character(1), allocatable, dimension(:) :: thedata
>
> len = getStringLengthFromAPI()
>
> allocate(thedata(len))
> call wrapperFunction(thedata, len)
>
> ! Other things happen with thedata here in the main program.
>
> contains
> subroutine wrapperFunction(thedata, len)
> character(1), dimension(:) :: thedata
> character(len) :: internalstring
>
> call getStringFromAPI(internalstring)
>
> ! The following line needs some cleverness added....
> thedata = internalstring
>
> end subroutine
> end
I like that. I was just hoping to avoid wrappers for the wrappers.
I'll work on it further next w .
>
> Similarly, any other cases where you're calling something on thedata
> that expects a scalar string can use the same sort of wrappers.
>
>
>
> The second part of what I'm suggesting is a further modification of the
> above pseudocode, implementing thedata as an ISO_VARYING_STRING rather
> than an array of character(1) as I've shown it.
>
> It won't do anything magical to fix the overall problem, as far as I
> know (I haven't looked at it too closely either), but it should make
> things like the "thedata = internalstring" operation easier, in that you
> won't have to implement your own loop over all the characters in the
> string for that.
>
> - Brooks
>
>
--
Gary Scott
mailto:garyscott@ev1.net
Fortran Library: http://www.fortranlib.com
Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html
Why are there two? God only knows.
If you want to do the impossible, don't hire an expert because he knows
it can't be done.
-- Henry Ford
| |
| gary.l.scott@lmco.com 2006-03-27, 7:02 pm |
| Interesting that Salford doesn't like this in one respect because
aString does not have a "target" attribute and won't allow assignment
of both pointer and target attributes to aString.
| |
| gary.l.scott@lmco.com 2006-03-28, 7:02 pm |
| It works with Lahey LF95 and Absoft if you reduce the pointer
declaration to a smaller size, I assume based upon actual physical
memory (268435455) available.
|
|
|
|
|