【问题标题】:Call 2d std::vector array from C++ to Fortran 90 error从 C++ 调用 2d std::vector 数组到 Fortran 90 错误
【发布时间】:2013-06-14 01:46:55
【问题描述】:

我正在尝试从 Fortran 90 调用以下 C++ 函数。

//Filename ctest.cpp
#include<iostream>
#include<vector>

extern "C"
{
  extern struct{
    std::vector< std::vector<double> > a;
    std::vector< std::vector<double> > b;
    std::vector< std::vector<double> > c;
  }abc_;
}

int myfunc_(int y,int z)
{
  std::vector< std::vector<double> > u(y,std::vector<double>(z,2.0));  
  std::vector< std::vector<double> > v(y,std::vector<double>(z,4.0));
  std::vector< std::vector<double> > w(y,std::vector<double>(z,6.0));

  abc_.a = u;
  abc_.b = v;
  abc_.c = w;

  return(1);
}

对应的fortran代码是 !文件 fortest.f90 ! Fortran 测试代码与 C++ 代码交互 !从 C++ 返回结构体

program fortest
implicit none
common/abc/ a,b,c
double precision,dimension(10,10) :: a
double precision,dimension(10,10) :: b
double precision,dimension(10,10) :: c

integer y,z

y = 10
z = 10

call myfunc(y,z)

write(*,*) a,b,c


stop

end

两个代码单独编译没有任何问题。但是,当我将 2 一起编译以将它们与

gfortran -o test fortest.o ctest.o

我收到一个非常大的错误消息。我怀疑问题在于 Fortran 无法识别 C++ 2d std::vector。但我在这里附上完整的信息,以防有人想看。

user@userpc$ gfortran -o test fortest.o ctest.o
fortest.o: In function `MAIN__':
fortest.f90:(.text+0x2d): undefined reference to `myfunc_'
ctest.o: In function `__static_initialization_and_destruction_0(int, int)':
ctest.cpp:(.text+0x379): undefined reference to `std::ios_base::Init::Init()'
ctest.cpp:(.text+0x37e): undefined reference to `std::ios_base::Init::~Init()'
ctest.o: In function `std::vector<double, std::allocator<double> >* std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >(unsigned long, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >)':
ctest.cpp:(.text._ZNSt6vectorIS_IdSaIdEESaIS1_EE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKS1_S3_EEEEPS1_mT_SB_[std::vector<double, std::allocator<double> >* std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >(unsigned long, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >)]+0x62): undefined reference to `__cxa_end_catch'
ctest.cpp:(.text._ZNSt6vectorIS_IdSaIdEESaIS1_EE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKS1_S3_EEEEPS1_mT_SB_[std::vector<double, std::allocator<double> >* std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >(unsigned long, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >)]+0x75): undefined reference to `__cxa_begin_catch'
ctest.cpp:(.text._ZNSt6vectorIS_IdSaIdEESaIS1_EE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKS1_S3_EEEEPS1_mT_SB_[std::vector<double, std::allocator<double> >* std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >(unsigned long, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >)]+0x91): undefined reference to `__cxa_rethrow'
ctest.o: In function `__gnu_cxx::new_allocator<std::vector<double, std::allocator<double> > >::deallocate(std::vector<double, std::allocator<double> >*, unsigned long)':
ctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorISt6vectorIdSaIdEEE10deallocateEPS3_m[__gnu_cxx::new_allocator<std::vector<double, std::allocator<double> > >::deallocate(std::vector<double, std::allocator<double> >*, unsigned long)]+0x1c): undefined reference to `operator delete(void*)'
ctest.o: In function `__gnu_cxx::new_allocator<double>::allocate(unsigned long, void const*)':
ctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv[__gnu_cxx::new_allocator<double>::allocate(unsigned long, void const*)]+0x2c): undefined reference to `std::__throw_bad_alloc()'
ctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorIdE8allocateEmPKv[__gnu_cxx::new_allocator<double>::allocate(unsigned long, void const*)]+0x3c): undefined reference to `operator new(unsigned long)'
ctest.o: In function `__gnu_cxx::new_allocator<double>::deallocate(double*, unsigned long)':
ctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorIdE10deallocateEPdm[__gnu_cxx::new_allocator<double>::deallocate(double*, unsigned long)]+0x1c): undefined reference to `operator delete(void*)'
ctest.o: In function `__gnu_cxx::new_allocator<std::vector<double, std::allocator<double> > >::allocate(unsigned long, void const*)':
ctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorISt6vectorIdSaIdEEE8allocateEmPKv[__gnu_cxx::new_allocator<std::vector<double, std::allocator<double> > >::allocate(unsigned long, void const*)]+0x2c): undefined reference to `std::__throw_bad_alloc()'
ctest.cpp:(.text._ZN9__gnu_cxx13new_allocatorISt6vectorIdSaIdEEE8allocateEmPKv[__gnu_cxx::new_allocator<std::vector<double, std::allocator<double> > >::allocate(unsigned long, void const*)]+0x45): undefined reference to `operator new(unsigned long)'
ctest.o: In function `std::vector<double, std::allocator<double> >* std::__uninitialized_copy<false>::__uninit_copy<std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*>(std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*)':
ctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIPSt6vectorIdSaIdEES5_EET0_T_S7_S6_[std::vector<double, std::allocator<double> >* std::__uninitialized_copy<false>::__uninit_copy<std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*>(std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*)]+0x62): undefined reference to `__cxa_end_catch'
ctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIPSt6vectorIdSaIdEES5_EET0_T_S7_S6_[std::vector<double, std::allocator<double> >* std::__uninitialized_copy<false>::__uninit_copy<std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*>(std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*)]+0x75): undefined reference to `__cxa_begin_catch'
ctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIPSt6vectorIdSaIdEES5_EET0_T_S7_S6_[std::vector<double, std::allocator<double> >* std::__uninitialized_copy<false>::__uninit_copy<std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*>(std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*, std::vector<double, std::allocator<double> >*)]+0x8d): undefined reference to `__cxa_rethrow'
ctest.o: In function `void std::__uninitialized_fill_n<false>::__uninit_fill_n<std::vector<double, std::allocator<double> >*, unsigned long, std::vector<double, std::allocator<double> > >(std::vector<double, std::allocator<double> >*, unsigned long, std::vector<double, std::allocator<double> > const&)':
ctest.cpp:(.text._ZNSt22__uninitialized_fill_nILb0EE15__uninit_fill_nIPSt6vectorIdSaIdEEmS4_EEvT_T0_RKT1_[void std::__uninitialized_fill_n<false>::__uninit_fill_n<std::vector<double, std::allocator<double> >*, unsigned long, std::vector<double, std::allocator<double> > >(std::vector<double, std::allocator<double> >*, unsigned long, std::vector<double, std::allocator<double> > const&)]+0x56): undefined reference to `__cxa_end_catch'
ctest.cpp:(.text._ZNSt22__uninitialized_fill_nILb0EE15__uninit_fill_nIPSt6vectorIdSaIdEEmS4_EEvT_T0_RKT1_[void std::__uninitialized_fill_n<false>::__uninit_fill_n<std::vector<double, std::allocator<double> >*, unsigned long, std::vector<double, std::allocator<double> > >(std::vector<double, std::allocator<double> >*, unsigned long, std::vector<double, std::allocator<double> > const&)]+0x69): undefined reference to `__cxa_begin_catch'
ctest.cpp:(.text._ZNSt22__uninitialized_fill_nILb0EE15__uninit_fill_nIPSt6vectorIdSaIdEEmS4_EEvT_T0_RKT1_[void std::__uninitialized_fill_n<false>::__uninit_fill_n<std::vector<double, std::allocator<double> >*, unsigned long, std::vector<double, std::allocator<double> > >(std::vector<double, std::allocator<double> >*, unsigned long, std::vector<double, std::allocator<double> > const&)]+0x81): undefined reference to `__cxa_rethrow'
ctest.o: In function `std::vector<double, std::allocator<double> >* std::__uninitialized_copy<false>::__uninit_copy<__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, std::vector<double, std::allocator<double> >*>(__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, std::vector<double, std::allocator<double> >*)':
ctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIN9__gnu_cxx17__normal_iteratorIPKSt6vectorIdSaIdEES4_IS6_SaIS6_EEEEPS6_EET0_T_SE_SD_[std::vector<double, std::allocator<double> >* std::__uninitialized_copy<false>::__uninit_copy<__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, std::vector<double, std::allocator<double> >*>(__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, std::vector<double, std::allocator<double> >*)]+0x7c): undefined reference to `__cxa_end_catch'
ctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIN9__gnu_cxx17__normal_iteratorIPKSt6vectorIdSaIdEES4_IS6_SaIS6_EEEEPS6_EET0_T_SE_SD_[std::vector<double, std::allocator<double> >* std::__uninitialized_copy<false>::__uninit_copy<__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, std::vector<double, std::allocator<double> >*>(__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, std::vector<double, std::allocator<double> >*)]+0x8f): undefined reference to `__cxa_begin_catch'
ctest.cpp:(.text._ZNSt20__uninitialized_copyILb0EE13__uninit_copyIN9__gnu_cxx17__normal_iteratorIPKSt6vectorIdSaIdEES4_IS6_SaIS6_EEEEPS6_EET0_T_SE_SD_[std::vector<double, std::allocator<double> >* std::__uninitialized_copy<false>::__uninit_copy<__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, std::vector<double, std::allocator<double> >*>(__gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, __gnu_cxx::__normal_iterator<std::vector<double, std::allocator<double> > const*, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > >, std::vector<double, std::allocator<double> >*)]+0xa7): undefined reference to `__cxa_rethrow'
ctest.o: In function `double* std::vector<double, std::allocator<double> >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > > >(unsigned long, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >)':
ctest.cpp:(.text._ZNSt6vectorIdSaIdEE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKdS1_EEEEPdmT_S9_[double* std::vector<double, std::allocator<double> >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > > >(unsigned long, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >)]+0x62): undefined reference to `__cxa_end_catch'
ctest.cpp:(.text._ZNSt6vectorIdSaIdEE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKdS1_EEEEPdmT_S9_[double* std::vector<double, std::allocator<double> >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > > >(unsigned long, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >)]+0x75): undefined reference to `__cxa_begin_catch'
ctest.cpp:(.text._ZNSt6vectorIdSaIdEE20_M_allocate_and_copyIN9__gnu_cxx17__normal_iteratorIPKdS1_EEEEPdmT_S9_[double* std::vector<double, std::allocator<double> >::_M_allocate_and_copy<__gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > > >(unsigned long, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >, __gnu_cxx::__normal_iterator<double const*, std::vector<double, std::allocator<double> > >)]+0x91): undefined reference to `__cxa_rethrow'
ctest.o:(.eh_frame+0x6b): undefined reference to `__gxx_personality_v0'
collect2: ld returned 1 exit status

知道什么是错的......一般来说,我如何在 fortran 中从 C++ 调用多维 std::vectors?这对从事计算科学的人非常有用。

【问题讨论】:

  • 试试gfortran -o test -lstdc++ fortest.o ctest.o,否则fortran不会知道c++标准库。
  • 我试过了,我仍然得到同样的错误......
  • 这行不通。在 C++ 中设置向量并将指向第一个元素的指针传递给 Fortran。忘记common。完全忘记它,尤其是在具有动态内存和多种语言的高级数据结构的情况下。

标签: c++ fortran


【解决方案1】:

std::vector 是一个对象,可以预期具有各种数据成员,例如容量、指向数据开始的指针、指向结束的指针等。标准没有指定确切的布局 -实现可能会有所不同。数据不直接存储在vector 中——通常是指向数据开始的指针地址堆分配的内存。因此,您不能只将 fortran 数组指向 vector 对象,因为它会期望双数据从该地址连续存储在内存中。您甚至不能使用 .data() 成员来获取指针指向的地址,因为在您的情况下,这是另一个 vector 并且有同样的问题。换句话说,您的数据在内存中并不连续,因此不会对应于二维数组的内存布局。

您可以尝试将数据复制到压缩的二维数组中:如果您知道维度将始终为 10x10,那么您可以使用堆栈分配区域,例如 double data[10][10],否则您可以使用 double* p = new double[100] 并将[x][y] 的逻辑值到元素 [x*10+y] 中。我猜测这就是您的 fortran 实现所期望的,但不确定。可能是它需要连续的数据,但使用[x+10*y] 打包它,或者它甚至可能引入一些其他填充。值得检查您的 fortran 文档。如果一切都失败了(或者你只是觉得这很有趣),你应该能够通过将数据放入 fortran 数组并在调试器中查看内存来计算布局来解决它。

【讨论】:

  • 托尼,+1。我已将数组定义为双精度数组,然后 g++ 对其进行编译。但是当我将 fortran 与 c++ 代码一起编译时,我得到了这个奇怪的错误:fortest.o: In function MAIN__': fortest.f90:(.text+0x2d): undefined reference to myfunc_' ctest.o: In function __static_initialization_and_destruction_0(int, int)': ctest.cpp:(.text+0x85): undefined reference to std::ios_base::Init::Init()' ctest.cpp:(.text+0x8a): undefined reference to `std::ios_base::Init::~Init()' collect2: ld returned 1 exit status 现在,不管我做什么,这是唯一无法理解的错误我明白了。!
  • @arvind:你在链接两个目标文件时使用 g++ 吗?似乎问题出在stackoverflow.com/questions/10906275/… - 可能需要-lstdc++。我很感激您在遵循 Seth 评论中的建议时尝试过,但您可能需要同时使用双精度数组并链接该库。如果它不起作用,请将您的完整编译/链接步骤和错误消息附加到问题中。干杯。
猜你喜欢
  • 1970-01-01
  • 2015-08-07
  • 2017-11-08
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-13
相关资源
最近更新 更多