<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic There is a third way, which in Intel® Fortran Compiler</title>
    <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087591#M123447</link>
    <description>&lt;P&gt;There is a third way, which you have not yet considered. This approach is the same as that used by the ctime() function of the standard C/Posix libraries. In this, only one string is allocated, and allocated statically (as in Fortran attribute SAVE). Each call to the function puts a different string into the string, and the pointer to the string remains the same. If saving the string is necessary, the caller of the routine has to do the saving before making the next call to the function.&lt;/P&gt;

&lt;P&gt;The function code is greatly simplified in this approach and, if the returned string is printed out (to screen or file) and not needed thereafter, there is no more to do. If the string is needed for use later, the programmer has a free hand in saving it in the caller using whatever facilities are provided by the language of the calling routine (C, Python, etc.).&lt;/P&gt;</description>
    <pubDate>Sat, 28 Nov 2015 17:18:00 GMT</pubDate>
    <dc:creator>mecej4</dc:creator>
    <dc:date>2015-11-28T17:18:00Z</dc:date>
    <item>
      <title>Fortran C interoperability: Returning string from Fortran to C</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087583#M123439</link>
      <description>&lt;P&gt;Hi, I'm building a C wrapper for my Fortran simulator to be used in Python. I made this function that takes the number of an element and returns its name:&lt;/P&gt;

&lt;PRE class="brush:fortran;"&gt;type(c_ptr) function get_elem_name(i) bind(C, name="get_elem_name")
#IFDEF DLL
!DEC$ ATTRIBUTES DLLEXPORT :: get_elem_name
#ENDIF
  use ELEMENTS, only: elemname, nbelem
  implicit none
  integer(c_int), INTENT(IN), value :: i
  character(len=21,kind=c_char) :: returnval
  returnval=''//C_NULL_CHAR
  if(i&amp;lt;=nbelem .and. i&amp;gt;0)returnval=trim(elemname(i))//C_NULL_CHAR
  get_elem_name = C_LOC(returnval)
end function get_elem_name&lt;/PRE&gt;

&lt;P&gt;It is called from Python as:&lt;/P&gt;

&lt;PRE class="brush:python;"&gt;import ctypes
mylib = ctypes.CDLL("mylib.dll")
mylib.init() # initialize simulator
mylib.get_elem_name(1) # get the name of the first element&lt;/PRE&gt;

&lt;P&gt;It works perfectly for the first 200 calls or something. After that, it randomly returns an empty string (''). I cannot get my head around the problem. Could it be that retval is automatically allocated inside Fortran and then the pointer passed to Python? Could that create an issue?&lt;/P&gt;

&lt;P&gt;Thanks for any help.&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 10:19:05 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087583#M123439</guid>
      <dc:creator>Petros</dc:creator>
      <dc:date>2015-11-28T10:19:05Z</dc:date>
    </item>
    <item>
      <title>It seems I fixed the problem.</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087584#M123440</link>
      <description>&lt;P&gt;It seems I fixed the problem. Instead of creating the string inside Fortran, I pass a buffer to fortran, fill the buffer, and get it back. The fortran code is:&lt;/P&gt;

&lt;PRE class="brush:fortran;"&gt;integer(c_int) function get_elem_name(i,name) bind(C, name="get_elem_name")
#IFDEF DLL
!DEC$ ATTRIBUTES DLLEXPORT :: get_elem_name
#ENDIF
use ELEMENTS, only: elemname, nbelem
character(c_char), dimension(21), intent(inout) :: name
character(len=21) :: f_name
integer :: n, j
name(1)=C_NULL_CHAR
if(i&amp;lt;=nbelem.and. i&amp;gt;0)then
   f_name=trim(elemname(i))
   n = len_trim(f_name)
   do j = 1, n
      name(j) = f_name(j:j)
   end do
   name(n + 1) = c_null_char
   get_elem_name= 0
   return
endif
get_elem_name= 1
end function get_elem_name&lt;/PRE&gt;

&lt;P&gt;The Python call becomes:&lt;/P&gt;

&lt;PRE class="brush:python;"&gt;import ctypes
mylib = ctypes.CDLL("mylib.dll")
mylib.init() # initialize simulator
name=ctypes.create_string_buffer(21)
mylib.get_elem_name(1,name) # get the name of the first element
name_str=name.value&lt;/PRE&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 13:04:31 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087584#M123440</guid>
      <dc:creator>Petros</dc:creator>
      <dc:date>2015-11-28T13:04:31Z</dc:date>
    </item>
    <item>
      <title>Your first case had two</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087585#M123441</link>
      <description>&lt;P&gt;Your first case had two pitfalls. 1) the returned address was to that which was local to the function. Depending on compiler options the buffer may or may not have been on the stack frame of your function and that frame goes out of scope upon return. While you could mitigate this by attributing the buffer with SAVE, this then restricts your code to having only one active returned element name. This may have been why you observed a null element (get element A, get element B-not found thus destroying element A return value). 2) returning a C_PTR, your code may erroneously attempt to perform a free. Though this may not be the case with your Python script as illustrated above,&amp;nbsp;it may affect your script as actually implemented.&lt;/P&gt;

&lt;P&gt;I suggest for your second implementation that you pass in the size of the buffer as opposed to assuming (requiring) it be 21 bytes long. This will give you more flexibility and be less error prone.&lt;/P&gt;

&lt;P&gt;Jim Dempsey&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 13:44:15 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087585#M123441</guid>
      <dc:creator>jimdempseyatthecove</dc:creator>
      <dc:date>2015-11-28T13:44:15Z</dc:date>
    </item>
    <item>
      <title>Here is what I think was</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087586#M123442</link>
      <description>&lt;P&gt;Here is what I think was happening with the code in #1, and why the fix of #2 worked.&lt;/P&gt;

&lt;P&gt;The variable&amp;nbsp;&lt;STRONG&gt;returnval &lt;/STRONG&gt;is a local variable. Therefore, once the function returns to the caller, the variable goes out of scope. It was allocated on the stack and code executed later may overwrite the variable and the memory that had been temporarily allocated on the stack to that variable may be reused as part of the stack of some other routine or in the caller itself.&lt;/P&gt;

&lt;P&gt;A variable that went out of scope may retain its value indefinitely. A pointer to the variable (pointer in the C sense) may yield the correct value when dereferenced, but this is not something that one can depend upon.&lt;/P&gt;

&lt;P&gt;P.S.: After pressing "SUBMIT", I found that Jim's reply had appeared. His diagnosis agrees with mine as to the main point.&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 14:05:00 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087586#M123442</guid>
      <dc:creator>mecej4</dc:creator>
      <dc:date>2015-11-28T14:05:00Z</dc:date>
    </item>
    <item>
      <title>Thanks Jim and mecej4. I</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087587#M123443</link>
      <description>&lt;P&gt;Thanks Jim and mecej4. I should have realized it was an issue with the allocation.&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 14:36:44 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087587#M123443</guid>
      <dc:creator>Petros</dc:creator>
      <dc:date>2015-11-28T14:36:44Z</dc:date>
    </item>
    <item>
      <title>My take on the problem is</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087588#M123444</link>
      <description>&lt;P&gt;My take on the problem is that you should go back to the original method but allocate the memory in the function. Also you should allocate using a technique that is consistent with the caller's dynamic memory scheme. Here is a fleshed out example with gfortran and gcc. ifort and cl should be similar.&lt;/P&gt;

&lt;PRE class="brush:fortran;"&gt;module elements
&amp;nbsp;&amp;nbsp; implicit none
&amp;nbsp;&amp;nbsp; integer, parameter :: nbelem = 109
&amp;nbsp;&amp;nbsp; character(13) :: elemname(nbelem) = [character(13) :: &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Hydrogen', 'Helium', 'Lithium', 'Beryllium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Boron', 'Carbon', 'Nitrogen', 'Oxygen', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Fluorine', 'Neon', 'Sodium', 'Magnesium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Aluminum', 'Silicon', 'Phosphorus', 'Sulfur', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Chlorine', 'Argon', 'Potassium', 'Calcium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Scandium', 'Titanium', 'Vanadium', 'Chromium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Manganese', 'Iron', 'Cobalt', 'Nickel', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Copper', 'Zinc', 'Gallium', 'Germanium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Arsenic', 'Selenium', 'Bromine', 'Krypton', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Rubidium', 'Strontium', 'Yttrium', 'Zirconium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Niobium', 'Molybdenum', 'Technetium', 'Ruthenium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Rhodium', 'Palladium', 'Silver', 'Cadmium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Indium', 'Tin', 'Antimony', 'Tellurium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Iodine', 'Xenon', 'Cesium', 'Barium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Lanthanum', 'Cerium', 'Praseodymium', 'Neodymium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Promethium', 'Samarium', 'Europium', 'Gadolinium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Terbium', 'Dysprosium', 'Holmium', 'Erbium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Thulium', 'Ytterbium', 'Lutetium', 'Hafnium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Tantalum', 'Tungsten', 'Rhenium', 'Osmium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Iridium', 'Platinum', 'Gold', 'Mercury', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Thallium', 'Lead', 'Bismuth', 'Polonium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Astatine', 'Radon', 'Francium', 'Radium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Actinium', 'Thorium', 'Protactinium', 'Uranium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Neptunium', 'Plutonium', 'Americium', 'Curium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Berkelium', 'Californium', 'Einsteinium', 'Fermium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Mendelevium', 'Nobelium', 'Lawrencium', 'Rutherfordium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Dubnium', 'Seaborgium', 'Bohrium', 'Hassium', &amp;amp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'Meitnerium']
end module elements

type(c_ptr) function get_elem_name(i) bind(C, name="get_elem_name")
&amp;nbsp;&amp;nbsp; use ELEMENTS, only: elemname, nbelem
&amp;nbsp;&amp;nbsp; use ISO_C_BINDING
&amp;nbsp;&amp;nbsp; implicit none
!DEC$ ATTRIBUTES DLLEXPORT :: get_elem_name
!gcc$ ATTRIBUTES DLLEXPORT :: get_elem_name
&amp;nbsp;&amp;nbsp; integer(c_int), INTENT(IN), value :: i
&amp;nbsp;&amp;nbsp; interface
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; function malloc(size) bind(C, name='malloc')
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; use ISO_C_BINDING
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; implicit none
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; type(C_PTR) malloc
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; integer(C_SIZE_T), value :: size
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; end function malloc
&amp;nbsp;&amp;nbsp; end interface
&amp;nbsp;&amp;nbsp; integer(C_SIZE_T) returnlen
&amp;nbsp;&amp;nbsp; character(len=21,kind=c_char) :: returnval
&amp;nbsp;&amp;nbsp; returnval=''//C_NULL_CHAR
&amp;nbsp;&amp;nbsp; if(i&amp;lt;=nbelem .and. i&amp;gt;0) then
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; returnlen = len_trim(elemname(i))+1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get_elem_name = malloc(returnlen)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BLOCK
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; character(returnlen), pointer :: returnval
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call C_F_POINTER(get_elem_name,returnval)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; returnval=trim(elemname(i))//C_NULL_CHAR
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; END BLOCK
&amp;nbsp;&amp;nbsp; else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; returnlen = 1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; get_elem_name = malloc(returnlen)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BLOCK
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; character(returnlen), pointer :: returnval
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; call C_F_POINTER(get_elem_name,returnval)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; returnval=C_NULL_CHAR
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; END BLOCK
&amp;nbsp;&amp;nbsp; end if
end function get_elem_name
&lt;/PRE&gt;

&lt;P&gt;Compiled with&lt;/P&gt;

&lt;P&gt;gfortran -shared get_elem_name.f90 -oget_elem_name.dll -Wl,--out-implib=libget_elem_name.a&lt;/P&gt;

&lt;PRE class="brush:cpp;"&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;

char *get_elem_name(int i);

int main()
{
&amp;nbsp;&amp;nbsp; char *result;
&amp;nbsp;&amp;nbsp; int i;

&amp;nbsp;&amp;nbsp; for(i = 0; i &amp;lt;= 100; i++)
&amp;nbsp;&amp;nbsp; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; result = get_elem_name(i);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; printf("%s\n",result);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; free(result);
&amp;nbsp;&amp;nbsp; }
&amp;nbsp;&amp;nbsp; return 0;
}
&lt;/PRE&gt;

&lt;P&gt;Compiled with&lt;/P&gt;

&lt;P&gt;gcc test.c -L. -lget_elem_name -otest&lt;/P&gt;

&lt;P&gt;And the whole thing did print out the elements :)&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 15:35:35 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087588#M123444</guid>
      <dc:creator>JVanB</dc:creator>
      <dc:date>2015-11-28T15:35:35Z</dc:date>
    </item>
    <item>
      <title>R.O.</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087589#M123445</link>
      <description>&lt;P&gt;R.O.&lt;/P&gt;

&lt;P&gt;While I agree that the allocation should be made using the application selected allocator, I think it is naïve to assume that the allocator is malloc. It could be any arbitrary allocator unknown to the Fortran code. Therefore, the allocation may be safer to be made in the scope of the calling application as opposed to by the Fortran subroutine. This said, if the allocation has to be made inside the Fortran code, then the safest way to do this is to pass in the allocator as part of the function call (but then your allocation interface must also be known).&lt;/P&gt;

&lt;P&gt;Jim Dempsey&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 16:58:21 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087589#M123445</guid>
      <dc:creator>jimdempseyatthecove</dc:creator>
      <dc:date>2015-11-28T16:58:21Z</dc:date>
    </item>
    <item>
      <title>Well, the problem with</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087590#M123446</link>
      <description>&lt;P&gt;Well, the problem with allocating inside my code is that then I would need to deallocate somehow and keep track inside Python of the elements allocated in Fortran to then call another fortran (or C) subroutine to deallocate them.&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 1em; line-height: 1.5;"&gt;Moreover, I don't see the benefit of this over what I did in the second example, where I allocate in python and pass the string to Fortran to be filled and returned. This way, the garbage collection of Python will take care of deallocating the string when not needed anymore (e.g. all references to the object removed).&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 1em; line-height: 1.5;"&gt;Can you elaborate on why (or when) one should allocate inside the fortran code?&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 1em; line-height: 1.5;"&gt;Thanks.&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 17:05:50 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087590#M123446</guid>
      <dc:creator>Petros</dc:creator>
      <dc:date>2015-11-28T17:05:50Z</dc:date>
    </item>
    <item>
      <title>There is a third way, which</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087591#M123447</link>
      <description>&lt;P&gt;There is a third way, which you have not yet considered. This approach is the same as that used by the ctime() function of the standard C/Posix libraries. In this, only one string is allocated, and allocated statically (as in Fortran attribute SAVE). Each call to the function puts a different string into the string, and the pointer to the string remains the same. If saving the string is necessary, the caller of the routine has to do the saving before making the next call to the function.&lt;/P&gt;

&lt;P&gt;The function code is greatly simplified in this approach and, if the returned string is printed out (to screen or file) and not needed thereafter, there is no more to do. If the string is needed for use later, the programmer has a free hand in saving it in the caller using whatever facilities are provided by the language of the calling routine (C, Python, etc.).&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 17:18:00 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087591#M123447</guid>
      <dc:creator>mecej4</dc:creator>
      <dc:date>2015-11-28T17:18:00Z</dc:date>
    </item>
    <item>
      <title>I am not suggesting</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087592#M123448</link>
      <description>&lt;P&gt;I am not suggesting allocation be made inside the Fortran code. What you did in the Python code is fine, with the possible exception of fixing the size&lt;/P&gt;

&lt;PRE class="brush:python;"&gt;import ctypes
mylib = ctypes.CDLL("mylib.dll")
mylib.init() # initialize simulator
name=ctypes.create_string_buffer(21)
mylib.get_elem_name(1,name,sizeof(name)) # get the name of the first element
name_str=name.value
&lt;/PRE&gt;

&lt;P&gt;May be a better solution (assuming your Fortran code has been changed too). Now, if your make a change in the Python code, you need not change the Fortran code.&lt;/P&gt;

&lt;P&gt;The Fortran code might be required to perform the allocation should the size of input not be known until the call. e.g. data located inside a Fortran written data file.&lt;/P&gt;

&lt;P&gt;Jim Dempsey&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 17:21:14 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087592#M123448</guid>
      <dc:creator>jimdempseyatthecove</dc:creator>
      <dc:date>2015-11-28T17:21:14Z</dc:date>
    </item>
    <item>
      <title>Well, when you return data of</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087593#M123449</link>
      <description>&lt;P&gt;Well, when you return data of size unknown before the call, there are potential problems. If you allocate a buffer to hold the data before the call, the buffer might not be big enough. I recall a previous thread where an example was posted that returned Windows error messages, and for most a couple of hundred bytes was serious overkill. The biggest messages turned out to be kilobytes. Windows itself has several APIs where you call them and tell them how big your buffer is and if it turns out to be too small, they return an error and give the required number of bytes in an INTENT(OUT) argument.&lt;/P&gt;

&lt;P&gt;The alternative is for the callee to provide the buffer to hold the data. The Fortran way would be to have a deferred-length allocatable result, which Fortran cleans up by itself after the expression containing the function reference is evaluated. Obviously python isn't going to be able to figure out how to do that. It has already been seen what happens when the buffer is provided in a location which is out of control of the caller.&lt;/P&gt;

&lt;P&gt;If a static buffer is used to return all results in, the function is not thread-safe and your code doesn't actually have to be multithreaded to expose thread-unsafe usage. For example, if a recursive procedure invokes the static-buffer-returning function, one instance can invisibly overwrite the data of another instance in a relatively difficult to debug fashion.&lt;/P&gt;

&lt;P&gt;Another method would be to have an array of NUL-terminated strings and just return a C pointer to the appropriate one, and this would work in my current example, but I don't know if you are just&amp;nbsp;indexing into&amp;nbsp;a table of constants or creating data more dynamically in the real code you want to use.&lt;/P&gt;

&lt;P&gt;You get around the above problems by allocating in the function that produces the data, but as you pointed out python has its own memory allocator (but you asked in the title how to return a string to C, so I just assumed that your program would know what to do with it...) but it seems there is a version with C interface identical to malloc() which is spelled PyMem_Malloc() which does in fact use python's memory management. So I might suggest that you change malloc to PyMem_Malloc in my example and perhaps link the *.DLL with some appropriate python run-time library and see if it then plays nice with your python code. Python should at least be able to free the memory itself; you would have to read some docs yourself to find out whether its garbage collector can do anything useful with it.&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 19:17:48 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087593#M123449</guid>
      <dc:creator>JVanB</dc:creator>
      <dc:date>2015-11-28T19:17:48Z</dc:date>
    </item>
    <item>
      <title>Thanks R.O. I'll take a look</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087594#M123450</link>
      <description>&lt;P&gt;Thanks R.O. I'll take a look at&amp;nbsp;&lt;SPAN style="font-size: 12px; line-height: 18px;"&gt;PyMem_Malloc! It looks interesting.&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Sat, 28 Nov 2015 19:39:17 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087594#M123450</guid>
      <dc:creator>Petros</dc:creator>
      <dc:date>2015-11-28T19:39:17Z</dc:date>
    </item>
    <item>
      <title>Quote:Repeat Offender wrote:</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087595#M123451</link>
      <description>&lt;P&gt;&lt;/P&gt;&lt;BLOCKQUOTE&gt;Repeat Offender wrote:&lt;BR /&gt;&lt;P&gt;&lt;/P&gt;

&lt;P&gt;Well, when you return data of size unknown before the call, there are potential problems. If you allocate a buffer to hold the data before the call, the buffer might not be big enough. ..&amp;nbsp;&lt;SPAN style="font-size: 12px; line-height: 18px;"&gt;there is a version with C interface identical to malloc() which is spelled PyMem_Malloc() ... Python should at least be able to free the memory itself; you would have to read some docs yourself to find out whether its garbage collector can do anything useful with it.&lt;/SPAN&gt;&lt;/P&gt;

&lt;P&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;&lt;/P&gt;

&lt;P&gt;Just noticed this thread: unless one has a need to really handle the memory management with fine-grained control of garbage collection, I recommend a much simpler approach using the enhanced interoperability with C feature in Fortran 2015 which Intel Fortran now largely supports (kudos to Intel!). &amp;nbsp;One can then perhaps write a C-processor based wrapper function that encapsulates the processing C-Fortran interface descriptor (CFI_cdesc_t type). &amp;nbsp;I've not used Python much, but I'd think one should be able to take the example below based on C and make use of standard functions like CFI_establish and CFI_deallocate to handle data on unknown size as well as free up the memory when done with Fortran dummy arguments having the ALLOCATABLE attribute: all one needs is the ISO_Fortran_binding.h file and the libraries from Intel Fortran compiler.&lt;/P&gt;

&lt;PRE class="brush:fortran;"&gt;module m

   use, intrinsic :: iso_c_binding, only : c_char, c_null_char, c_int

   implicit none

   private

   integer, parameter :: MAXELEM = 5
   character(kind=c_char,len=*), parameter :: Elements(MAXELEM) = [ character(kind=c_char,len=40) ::&amp;amp;
      c_char_"Earth", c_char_"Fire", c_char_"Water", c_char_"Wind",                                 &amp;amp;
      c_char_"That mysterious one called ether!" ]

   public :: get_elem_name

contains

   pure subroutine get_elem_name(Ielem, ElemName, ErrorCode) bind(C, name="get_elem_name")

      !.. Argument list
      integer(c_int), value, intent(in)                      :: Ielem
      character(kind=c_char,len=1), allocatable, intent(out) :: ElemName(:)
      integer(c_int), intent(inout)                          :: ErrorCode

      !.. Local variables
      integer :: I
      integer :: LenName

      if ( (Ielem &amp;gt;= 1).and.(Ielem &amp;lt;= size(Elements)) ) then
         LenName = len_trim(Elements(Ielem))
         allocate( ElemName(LenName+1), stat=ErrorCode )
         if (ErrorCode == 0) then
            forall (I = 1:LenName)
               ElemName(I) = Elements(Ielem)(I:I)
            end forall
            ElemName(LenName+1) = c_null_char
         end if
      else
         allocate( ElemName(1), stat=ErrorCode )
         if (ErrorCode == 0) then
            ElemName(1) = c_null_char
         end if
         ErrorCode = 1
      end if

      return

   end subroutine get_elem_name

end module m
&lt;/PRE&gt;

&lt;PRE class="brush:cpp;"&gt;#include &amp;lt;stdio.h&amp;gt;
#include "ISO_Fortran_binding.h"

// Prototype for C wrapper function
char* getelem(int i, CFI_cdesc_t * dv);
// Prototype for Fortran getter function
void get_elem_name(int i, CFI_cdesc_t * dv, int *irc);

int main()
{

   CFI_CDESC_T(1) fortran_object;
   char* elem_name;
   int irc;

   // Call C wrapper function
   elem_name = getelem(5, (CFI_cdesc_t *)&amp;amp;fortran_object);

   if (elem_name != NULL) {
      printf("element name: %s\n", elem_name);
   }
   else {
      printf("failed to get element name.\n");
   }

   // Free the CFI decriptor object for Fortran-C interoperability
   irc = CFI_deallocate((CFI_cdesc_t *)&amp;amp;fortran_object);

   return 0;

}
// Wrapper function to Fortran get_elem_name procedure
char* getelem(int i, CFI_cdesc_t * dv)
{

   int irc;
   CFI_rank_t rank;

   irc = 0;
   rank = 1;
   irc = CFI_establish(dv, NULL,
      CFI_attribute_allocatable,
      CFI_type_char, sizeof(char *), rank, NULL);
   if (irc != CFI_SUCCESS) {
      return NULL;
   }

   // Call Fortran function
   get_elem_name(i, dv, &amp;amp;irc);

   if (irc == 0) {
      return (char *)dv-&amp;gt;base_addr;
   }
   else {
      return NULL;
   }

}
&lt;/PRE&gt;

&lt;P&gt;Upon execution,&lt;/P&gt;

&lt;PRE class="brush:plain;"&gt;element name: That mysterious one called ether!
Press any key to continue . . .&lt;/PRE&gt;

&lt;P&gt;Of course, if the data sizes are known up front or when the caller only wants to deal with data of certain sizes, it's best if the Fortran interface receives the buffer along with the buffer length information and the Fortran interface has the dummy argument(s) for data with assumed size attribute; also, I prefer using subroutines (i.e., void C functions) over a function returning the data (as in the original post which is a no-go in interoperating schemes) or the common C practice of returning an error code as function result and data via the function parameter.&lt;/P&gt;</description>
      <pubDate>Mon, 30 Nov 2015 23:57:25 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087595#M123451</guid>
      <dc:creator>FortranFan</dc:creator>
      <dc:date>2015-11-30T23:57:25Z</dc:date>
    </item>
    <item>
      <title>Hi @FortranFan. Wow, I didn't</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087596#M123452</link>
      <description>&lt;P&gt;Hi @FortranFan. Wow, I didn't know about this functionality. I always thought interoperability was kind of one-direction: A way to wrap Fortran so it plays nice with the "now-a-days" standard language C.&lt;/P&gt;

&lt;P&gt;It's good you posted your solution here for completeness and future reference. However, I believe it's an overkill for what I need. The data structure is well known beforehand (character len=20), so I prefer to pass a buffer and get the info, as in my 2nd post.&lt;/P&gt;

&lt;P&gt;If I was programming in C, then I would need to allocate, keep track, and deallocate anyway, so your proposed approach makes sense. It adds functionality and robustness without any extra cost.&lt;/P&gt;

&lt;P&gt;Nevertheless, in Python, you don't need to do it yourself (otherwise why opt for a slower language). It takes care to free memory automatically (e.g. once an object is not referenced anywhere in the program anymore, etc.). So, to manually track memory, allocate and deallocate is not really the "Pythonic" way.&lt;/P&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 01 Dec 2015 09:06:02 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087596#M123452</guid>
      <dc:creator>Petros</dc:creator>
      <dc:date>2015-12-01T09:06:02Z</dc:date>
    </item>
    <item>
      <title>Quote:FortranFan wrote:, I</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087597#M123453</link>
      <description>&lt;P&gt;&lt;/P&gt;&lt;BLOCKQUOTE&gt;FortranFan wrote:&lt;BR /&gt;&lt;SPAN style="font-size: 1em; line-height: 1.5;"&gt;, I recommend a much simpler approach using the enhanced interoperability with C feature in Fortran 2015 which Intel Fortran now largely supports (kudos to Intel!). &amp;nbsp;&lt;/SPAN&gt;&lt;SPAN style="font-size: 1em; line-height: 1.5;"&gt;&lt;/SPAN&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;&lt;/P&gt;

&lt;P&gt;&lt;SPAN style="font-size: 1em; line-height: 1.5;"&gt;"largely"? As far as I know, we support it entirely. What do you think we're missing? (Not counting the inevitable bugs, though I know of only one minor one at this time.)&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Tue, 01 Dec 2015 12:48:10 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087597#M123453</guid>
      <dc:creator>Steven_L_Intel1</dc:creator>
      <dc:date>2015-12-01T12:48:10Z</dc:date>
    </item>
    <item>
      <title>Quote:Steve Lionel (Intel)</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087598#M123454</link>
      <description>&lt;P&gt;&lt;/P&gt;&lt;BLOCKQUOTE&gt;Steve Lionel (Intel) wrote:&lt;BR /&gt;&lt;P&gt;&lt;/P&gt;

&lt;P&gt;&lt;STRONG class="quote-header"&gt;Quote:&lt;/STRONG&gt;&lt;/P&gt;

&lt;BLOCKQUOTE class="quote-msg quote-nest-1 odd"&gt;
	&lt;DIV class="quote-author"&gt;&lt;EM class="placeholder"&gt;FortranFan&lt;/EM&gt; wrote:&lt;/DIV&gt;
	, I recommend a much simpler approach using the enhanced interoperability with C feature in Fortran 2015 which Intel Fortran now largely supports (kudos to Intel!). &amp;nbsp;&lt;/BLOCKQUOTE&gt;

&lt;P&gt;&amp;nbsp;&lt;/P&gt;

&lt;P&gt;"largely"? As far as I know, we support it entirely. What do you think we're missing? (Not counting the inevitable bugs, though I know of only one minor one at this time.)&lt;/P&gt;

&lt;P&gt;&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;&lt;/P&gt;

&lt;P&gt;Steve,&lt;/P&gt;

&lt;P&gt;My choice of the word wasn't all that deliberate, I suppose I meant it suppositionally since the standard itself is unofficial yet (sure, members might feel TS 29113 aspect is not going to change but you know the cliche, it ain't over til..) and I'd a vague impression about some gap/issue (I could be wrong on this) with the assumed type, shape, and rank aspect either in Intel Fortran or in the standard itself.&lt;/P&gt;

&lt;P&gt;Anyways, I'm happy to see Intel take the lead on this and strive to get all of TS 29113 aspect of Fortran 2015 implemented when it did; I like the approach and hope it can be extended quickly to other aspects of the standard too! &amp;nbsp;But first, I would like to see the rest of Fortran 2008 implemented - it's that of the season again: can we wish for ALL of Fortran 2008 in year 2016 and ALL of Fortran 2015 within a year of standard being "finalized", (year 2018?!)&lt;/P&gt;</description>
      <pubDate>Tue, 01 Dec 2015 15:39:52 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087598#M123454</guid>
      <dc:creator>FortranFan</dc:creator>
      <dc:date>2015-12-01T15:39:52Z</dc:date>
    </item>
    <item>
      <title>Yes, assumed type and rank</title>
      <link>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087599#M123455</link>
      <description>&lt;P&gt;Yes, assumed type and rank are supported now. Nothing material is going to change for F2015 - I did discover some editorial issues that we (standards committee) took care of - no technical changes. I'm not aware of any gaps in our implementation. I know that gfortran has some of the TS but not the part that deals with C descriptors (yet).&lt;/P&gt;

&lt;P&gt;Getting all of F2008 is our (Intel's) primary goal at this point, though some things from F2015 (such as the Interop TS) are too popular/important to put off.&lt;/P&gt;</description>
      <pubDate>Tue, 01 Dec 2015 16:36:08 GMT</pubDate>
      <guid>https://community.intel.com/t5/Intel-Fortran-Compiler/Fortran-C-interoperability-Returning-string-from-Fortran-to-C/m-p/1087599#M123455</guid>
      <dc:creator>Steven_L_Intel1</dc:creator>
      <dc:date>2015-12-01T16:36:08Z</dc:date>
    </item>
  </channel>
</rss>

