[Ipopt] string array to ipopt-fortran
Jonathan Hogg
jonathan.hogg at stfc.ac.uk
Mon Mar 26 09:05:10 EDT 2012
Fabian,
Fortran character variables normally have a defined length, so arrays
can be handled via a simple byte offset. They also carry their length
around with them in some fashion. This makes character(len=*) arrays a
bit of a funny beast, and probably compiler dependent how they are
implemented. I doubt you can pass anything from C that matches the type
without using the latest draft TR from the Fortran standards committee
(though I think this is implemented in this month's release of gcc).
C-style strings (different from C++-style strings defined using the C++
'string' class) as you use here are pointers, so char ** is an array of
pointers to pointers.
You need to unwrap the C-style string array to a Fortran one. Something
like the following code might work (I've not run it past a compiler, so
there may be mistakes)
subroutine foo (nstr, maxlen, c_str_array) bind(C)
use iso_c_binding
integer(C_INT), value :: nstr, maxlen
type(C_PTR), dimension(nstr) :: c_str_array
integer :: i, j
character(kind=C_CHAR, len=1), dimension(:), pointer :: str_ptr
character(kind=C_CHAR, len=maxlen), dimension(nstr) :: f_str_array
do i=1, nstr
call C_F_POINTER(c_str_array(i), str_ptr, shape=(/ maxlen /) )
do j=1,maxlen
f_str_array(i:i) = str_ptr(i)
end do
end do
! Use f_str_array(:) to do useful things...
end subroutine foo
Jonathan.
On 26/03/12 11:24, Fabian Wein wrote:
> Hi Jonathan,
>
> thanks for your reply.
>
> My plan is to pass from C++ strings and length's and convert it.
>
> This is my current test:
>
> C-Header:...
> const int* ipopt_nargs, // ON INPUT (I): Number of
> parameters passed to IPOPT23
> double* ipopt_args, // ON INPUT (I): Values passed
> to IPOPT23
> char** ipopt_cargs_c, // ON INPUT (I): name of
> parameters passed to IPOPT23
> int* ipopt_cargs_l); // ON INPUT (I): length's of
> the parameter names
>
>
> SUBROUTINE ....
> INTEGER IPOPT_NARGS,IPOPT_CARGS_L(*),IPOPT_TMP
> DOUBLE PRECISION IPOPT_ARGS(*)
> CHARACTER*(*) IPOPT_CARGS_C(*)
> CHARACTER*256 IPOPT_CARGS(50), IPOPT_TMP_STR
>
> C We need to transfer the ipopt subsolver options from C which are
> C an array of strings.
> DO 1220 IPOPT_TMP = 1, IPOPT_NARGS
> IPOPT_TMP_STR(1:IPOPT_CARGS_L(IPOPT_TMP)) =
> + IPOPT_CARGS_C(IPOPT_TMP)
> IPOPT_CARGS(1) = IPOPT_TMP_STR;
> WRITE(*, *) 'param/leng/str:', IPOPT_TMP,
> + IPOPT_CARGS_L(IPOPT_TMP), IPOPT_TMP_STR
> 1220 CONTINUE
>
> This does not work:
> param/leng/str: 1 4 <a lot of garbage>
>
> Why so much garbage? Would expect at maximum 4 characters of garbage ?!
>
> Any further help is very much appreciated. I need this to run first,
> then I want
> to replace the old Ipopt with the current one. I started to dig into
> Fortran on Friday only -
> and hope to have nothing to do with Fortran any more once I replaced
> Ipopt. :)
>
> Currently I try to understand how to use this iso_c_binding module.
>
>> In general C/Fortran interoperability terms, I'd recommend you use the
>> iso_c_binding module.
>> Note that C-style strings are generally character*1 arrays on the
>> Fortran side. To determine length you'll need to pass the length
>> separately to the string (or call strlen from Fortran).
>>
>> This may mean you need a wrapper on the Fortran side that translates
>> arguments nicely and then calls your Fortran subroutine that takes
>> character(len=*) arguments. (If I've understood your question directly).
>>
>> Of course, the Fortran version of Ipopt has been replaced by the C++
>> version, so longer term you probably want to move away from
>> Ipopt-Fortran.
>>
>> Jonathan.
>>
>> On 26/03/12 10:15, Fabian Wein wrote:
>>> Hi,
>>>
>>> I have to use an Fortran code that uses Ipopt-Fortran from C++. I
>>> want to pass
>>> the Ipopt parameters from C++ via Fortran.
>>>
>>> Is there any example available on how to use the CHARACTER*(*) CARGS
>>> from
>>> C? I use gfortran.
> _______________________________________________
> Ipopt mailing list
> Ipopt at list.coin-or.org
> http://list.coin-or.org/mailman/listinfo/ipopt
--
Scanned by iCritical.
More information about the Ipopt
mailing list