{"id":869,"date":"2022-08-30T15:08:32","date_gmt":"2022-08-30T15:08:32","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2013\/11\/09\/call-2d-stdvector-array-from-c-to-fortran-90-error-collection-of-common-programming-errors\/"},"modified":"2022-08-30T15:08:32","modified_gmt":"2022-08-30T15:08:32","slug":"call-2d-stdvector-array-from-c-to-fortran-90-error-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2022\/08\/30\/call-2d-stdvector-array-from-c-to-fortran-90-error-collection-of-common-programming-errors\/","title":{"rendered":"Call 2d std::vector array from C++ to Fortran 90 error-Collection of common programming errors"},"content":{"rendered":"<p>I am trying to call the following C++ function from Fortran 90.<\/p>\n<pre><code>\/\/Filename ctest.cpp\n#include\n#include\n\nextern \"C\"\n{\n  extern struct{\n    std::vector&lt; std::vector &gt; a;\n    std::vector&lt; std::vector &gt; b;\n    std::vector&lt; std::vector &gt; c;\n  }abc_;\n}\n\nint myfunc_(int y,int z)\n{\n  std::vector&lt; std::vector &gt; u(y,std::vector(z,2.0));  \n  std::vector&lt; std::vector &gt; v(y,std::vector(z,4.0));\n  std::vector&lt; std::vector &gt; w(y,std::vector(z,6.0));\n\n  abc_.a = u;\n  abc_.b = v;\n  abc_.c = w;\n\n  return(1);\n}\n<\/code><\/pre>\n<p>The corresponding fortran code is ! File fortest.f90 ! Fortran test code to interface with C++ code ! return struct from C++<\/p>\n<pre><code>program fortest\nimplicit none\ncommon\/abc\/ a,b,c\ndouble precision,dimension(10,10) :: a\ndouble precision,dimension(10,10) :: b\ndouble precision,dimension(10,10) :: c\n\ninteger y,z\n\ny = 10\nz = 10\n\ncall myfunc(y,z)\n\nwrite(*,*) a,b,c\n\n\nstop\n\nend\n<\/code><\/pre>\n<p>Both codes compile without any problems individually. However, when I compile the 2 together to interface them, with<\/p>\n<pre><code>gfortran -o test fortest.o ctest.o\n<\/code><\/pre>\n<p>I get a really huge error message. I suspect the problem is with Fortran not recognizing C++ 2d std::vector. But I am enclosing the full message here in case anyone wants to have a look.<\/p>\n<pre><code>user@userpc$ gfortran -o test fortest.o ctest.o\nfortest.o: In function `MAIN__':\nfortest.f90:(.text+0x2d): undefined reference to `myfunc_'\nctest.o: In function `__static_initialization_and_destruction_0(int, int)':\nctest.cpp:(.text+0x379): undefined reference to `std::ios_base::Init::Init()'\nctest.cpp:(.text+0x37e): undefined reference to `std::ios_base::Init::~Init()'\nctest.o: In function `std::vector* std::vector::_M_allocate_and_copy(unsigned long, __gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator)':\nctest.cpp:(.text._ZNSt6vectorIS_IdSaIdEESaIS1_EE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKS1_S3_EEEEPS1_mT_SB_[std::vector* std::vector::_M_allocate_and_copy(unsigned long, __gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator)]+0x62): undefined reference to `__cxa_end_catch'\nctest.cpp:(.text._ZNSt6vectorIS_IdSaIdEESaIS1_EE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKS1_S3_EEEEPS1_mT_SB_[std::vector* std::vector::_M_allocate_and_copy(unsigned long, __gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator)]+0x75): undefined reference to `__cxa_begin_catch'\nctest.cpp:(.text._ZNSt6vectorIS_IdSaIdEESaIS1_EE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKS1_S3_EEEEPS1_mT_SB_[std::vector* std::vector::_M_allocate_and_copy(unsigned long, __gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator)]+0x91): undefined reference to `__cxa_rethrow'\nctest.o: In function `__gnu_cxx::new_allocator::deallocate(std::vector*, unsigned long)':\nctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorISt6vectorIdSaIdEEE10deallocateEPS3_m[__gnu_cxx::new_allocator::deallocate(std::vector*, unsigned long)]+0x1c): undefined reference to `operator delete(void*)'\nctest.o: In function `__gnu_cxx::new_allocator::allocate(unsigned long, void const*)':\nctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv[__gnu_cxx::new_allocator::allocate(unsigned long, void const*)]+0x2c): undefined reference to `std::__throw_bad_alloc()'\nctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv[__gnu_cxx::new_allocator::allocate(unsigned long, void const*)]+0x3c): undefined reference to `operator new(unsigned long)'\nctest.o: In function `__gnu_cxx::new_allocator::deallocate(double*, unsigned long)':\nctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorIdE10deallocateEPdm[__gnu_cxx::new_allocator::deallocate(double*, unsigned long)]+0x1c): undefined reference to `operator delete(void*)'\nctest.o: In function `__gnu_cxx::new_allocator::allocate(unsigned long, void const*)':\nctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorISt6vectorIdSaIdEEE8allocateEmPKv[__gnu_cxx::new_allocator::allocate(unsigned long, void const*)]+0x2c): undefined reference to `std::__throw_bad_alloc()'\nctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorISt6vectorIdSaIdEEE8allocateEmPKv[__gnu_cxx::new_allocator::allocate(unsigned long, void const*)]+0x45): undefined reference to `operator new(unsigned long)'\nctest.o: In function `std::vector* std::__uninitialized_copy::__uninit_copy(std::vector*, std::vector*, std::vector*)':\nctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIPSt6vectorIdSaIdEES5_EET0_T_S7_S6_[std::vector* std::__uninitialized_copy::__uninit_copy(std::vector*, std::vector*, std::vector*)]+0x62): undefined reference to `__cxa_end_catch'\nctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIPSt6vectorIdSaIdEES5_EET0_T_S7_S6_[std::vector* std::__uninitialized_copy::__uninit_copy(std::vector*, std::vector*, std::vector*)]+0x75): undefined reference to `__cxa_begin_catch'\nctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIPSt6vectorIdSaIdEES5_EET0_T_S7_S6_[std::vector* std::__uninitialized_copy::__uninit_copy(std::vector*, std::vector*, std::vector*)]+0x8d): undefined reference to `__cxa_rethrow'\nctest.o: In function `void std::__uninitialized_fill_n::__uninit_fill_n(std::vector*, unsigned long, std::vector const&amp;)':\nctest.cpp:(.text._ZNSt22__uninitialized_fill_nILb0EE15__uninit_fill_nIPSt6vectorIdSaIdEEmS4_EEvT_T0_RKT1_[void std::__uninitialized_fill_n::__uninit_fill_n(std::vector*, unsigned long, std::vector const&amp;)]+0x56): undefined reference to `__cxa_end_catch'\nctest.cpp:(.text._ZNSt22__uninitialized_fill_nILb0EE15__uninit_fill_nIPSt6vectorIdSaIdEEmS4_EEvT_T0_RKT1_[void std::__uninitialized_fill_n::__uninit_fill_n(std::vector*, unsigned long, std::vector const&amp;)]+0x69): undefined reference to `__cxa_begin_catch'\nctest.cpp:(.text._ZNSt22__uninitialized_fill_nILb0EE15__uninit_fill_nIPSt6vectorIdSaIdEEmS4_EEvT_T0_RKT1_[void std::__uninitialized_fill_n::__uninit_fill_n(std::vector*, unsigned long, std::vector const&amp;)]+0x81): undefined reference to `__cxa_rethrow'\nctest.o: In function `std::vector* std::__uninitialized_copy::__uninit_copy(__gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator, std::vector*)':\nctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIN9__gnu_cxx17__normal_iteratorIPKSt6vectorIdSaIdEES4_IS6_SaIS6_EEEEPS6_EET0_T_SE_SD_[std::vector* std::__uninitialized_copy::__uninit_copy(__gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator, std::vector*)]+0x7c): undefined reference to `__cxa_end_catch'\nctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIN9__gnu_cxx17__normal_iteratorIPKSt6vectorIdSaIdEES4_IS6_SaIS6_EEEEPS6_EET0_T_SE_SD_[std::vector* std::__uninitialized_copy::__uninit_copy(__gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator, std::vector*)]+0x8f): undefined reference to `__cxa_begin_catch'\nctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIN9__gnu_cxx17__normal_iteratorIPKSt6vectorIdSaIdEES4_IS6_SaIS6_EEEEPS6_EET0_T_SE_SD_[std::vector* std::__uninitialized_copy::__uninit_copy(__gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator, std::vector*)]+0xa7): undefined reference to `__cxa_rethrow'\nctest.o: In function `double* std::vector::_M_allocate_and_copy(unsigned long, __gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator)':\nctest.cpp:(.text._ZNSt6vectorIdSaIdEE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKdS1_EEEEPdmT_S9_[double* std::vector::_M_allocate_and_copy(unsigned long, __gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator)]+0x62): undefined reference to `__cxa_end_catch'\nctest.cpp:(.text._ZNSt6vectorIdSaIdEE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKdS1_EEEEPdmT_S9_[double* std::vector::_M_allocate_and_copy(unsigned long, __gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator)]+0x75): undefined reference to `__cxa_begin_catch'\nctest.cpp:(.text._ZNSt6vectorIdSaIdEE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKdS1_EEEEPdmT_S9_[double* std::vector::_M_allocate_and_copy(unsigned long, __gnu_cxx::__normal_iterator, __gnu_cxx::__normal_iterator)]+0x91): undefined reference to `__cxa_rethrow'\nctest.o:(.eh_frame+0x6b): undefined reference to `__gxx_personality_v0'\ncollect2: ld returned 1 exit status\n<\/code><\/pre>\n<p>Any idea whats wrong&#8230;. in general terms how do I call multidimensional std::vectors from C++ in fortran? This will be of great use to people doing computational sciences.<\/p>\n<ol>\n<li>\n<p><code>std::vector<\/code> is an object that can be expected to have various data members such as capacity, pointer-to-start-of-data, pointer-to-end etc.. The exact layout is not specified by the Standard &#8211; implementations may vary. The data is not stored directly in the <code>vector<\/code> &#8211; normally the pointer-to-start-of-data addresses heap-allocated memory. Therefore, you can&#8217;t just point a fortran array at the <code>vector<\/code> object, as it will expect double data to be contiguously in memory from that address. You can&#8217;t even use the <code>.data()<\/code> member to get the address where the pointer points, as in your case that&#8217;s another <code>vector<\/code> and has the same problem. Put another way, your data just isn&#8217;t contiguous in memory so won&#8217;t correspond to the memory layout for a 2-dimensional array.<\/p>\n<p>You could try copying the data into a packed two-dimensional array: if you know the dimensions will always be 10&#215;10, then you can use a stack allocated area such as <code>double data[10][10]<\/code>, otherwise you can <code>double* p = new double[100]<\/code> and put the logical value for <code>[x][y]<\/code> into element <code>[x*10+y]<\/code>. I&#8217;m <em>guessing<\/em> that&#8217;s what your fortran implementation will expect but don&#8217;t know for sure. It could be that it will expect contiguous data but packs it using <code>[x+10*y]<\/code>, or it&#8217;s even possible that it might introduce some other padding. It&#8217;s worth checking with your fortran documentation. If all else fails (or you just think it&#8217;s fun) you should be able to work it out by putting data into the fortran array and looking at the memory in a debugger to work out the layout.<\/p>\n<\/li>\n<\/ol>\n<p id=\"rop\"><small>Originally posted 2013-11-09 22:50:02. <\/small><\/p>","protected":false},"excerpt":{"rendered":"<p>I am trying to call the following C++ function from Fortran 90. \/\/Filename ctest.cpp #include #include extern &#8220;C&#8221; { extern struct{ std::vector&lt; std::vector &gt; a; std::vector&lt; std::vector &gt; b; std::vector&lt; std::vector &gt; c; }abc_; } int myfunc_(int y,int z) { std::vector&lt; std::vector &gt; u(y,std::vector(z,2.0)); std::vector&lt; std::vector &gt; v(y,std::vector(z,4.0)); std::vector&lt; std::vector &gt; w(y,std::vector(z,6.0)); abc_.a = u; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-869","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/869","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=869"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/869\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=869"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=869"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=869"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}