How should multiple Fortran strings be passed to C? -


to pass fortran string c, hidden parameter passed variable's size. here's working fortran definition, , c (actually c++/cli) method:

  interface      subroutine appendextension(  +      filename)  +      bind(c, name="appendextension")      character *1, intent(inout):: filename     end subroutine appendextension   end interface 

and here's c++/cli gets called:

extern "c" {   void __declspec(dllexport) __cdecl appendextension(                                          char * name,                                           int buffersize) {   string^ clistr = gcnew string(name);   clistr = system::io::path::changeextension(clistr->trim(), gcnew string("out"));   intptr p = marshal::stringtohglobalansi(clistr);   char *pnewcharstr = static_cast<char*>(p.topointer());   int cstrlen = strlen(pnewcharstr);   memcpy_s(name, buffersize, pnewcharstr, cstrlen);   if (cstrlen < buffersize)   {     // backfill spaces, since fortran string spaces on right.     memset(&name[cstrlen], ' ', buffersize-cstrlen);   }   marshal::freehglobal(p); } 

the above working (intel visual fortran 2013 sp1).

i want pass 2 strings function. here's did:

   interface      subroutine parsespec(  +      filename, corename)  +      bind(c, name="parsespec")      character *1, intent(inout):: filename      character *1, intent(inout):: corename     end subroutine parsespec    end interface 

here's call in action:

      character*80 file_spec       character*200 core_name       call parsespec(file_spec, core_name) 

and here's c++/cli:

void __declspec(dllexport) __cdecl parsespec(char * name, char * corename, int namelen, int corelen) {   // namelen , corelen both contain length of "name".   ... 

there 2 hidden variables. think should buffersizes each of 2 strings, 1 "filename" , 1 "corename". both contain buffer size of first buffer, namely 80.

where going wrong?

the calling convention bind(c) procedures can quite different default calling convention fortran compiler uses fortran fortran calls. should not rely on hidden character length arguments (in general case, shouldn't expect hidden arguments of type int). suspect have been lucky, given way fortran character variable laid out in memory compiler.

there no need compiler pass length bind(c) procedure, because length of character variable interoperable c one. however, if dummy argument array (which want if passing string, rather individual character), size of array may non-negative - rules of fortran sequence association kind=c_char character mean can associate scalar array.

all - change fortran function declaration such character arguments arrays , add arguments explicitly pass length of arrays.

using free form source, , assuming default character same c_char kind:

interface   subroutine parsespec(  &         name, name_len,  &         corename, corename_len )  &       bind(c, name="parsespec")     use, intrinsic :: iso_c_binding, only: c_int, c_char     integer(c_int), value :: name_len     character(kind=c_char), intent(inout) :: name(name_len)     integer(c_int), value :: corename_len     character(kind=c_char), intent(inout):: corename(corename_len)   end subroutine parsespec end interface  use, intrinsic :: iso_c_binding, only: c_int character*80 file_spec character*200 core_name call parsespec(  &     file_spec, len(file_spec, kind=c_int),  &     core_name, len(core_name, kind=c_int) ) 
extern "c" void parsespec(      char* name, int name_len,      char* corename, int corelen ); // operations on name[0] name[name_len-1] ,  // corename[0] through corename[core_len-1]... 

Comments

Popular posts from this blog

get url and add instance to a model with prefilled foreign key :django admin -

css - Make div keyboard-scrollable in jQuery Mobile? -

ruby on rails - Seeing duplicate requests handled with Unicorn -