2012-05-07 49 views
2

我试图从C++访问Fortran公共块结构中的数组。
我有一个与C++和Fortran混合的示例代码。C++和Fortran:从C++访问Fortran公共块中的数组时出错Error

Fortran语言:

integer a(5),b 
common /sample/ a,b 
a(1) = 1 
a(2) = 5 
a(3) = 10 
a(4) = 15 
a(5) = 20 
b = 25 

然后在C++:

extern "C"{ 
    extern struct{ 
     int *a,b; 
}sample_; 

从C++,如果我尝试打印值sample_.b

printf("sample b:%d\n",sample_.b); 

我得到的值( 2):sample b:5

如果我尝试打印任何其他数组a值我只是得到一个segementation故障...

printf("sample_.a[1]=%d\n",(int)sample_.a[1]); 
printf("sample_.a[0]=%d\n",(int)sample_.a[0]); 

我在做什么错?¿任何想法¿?
我想,也许我必须将数组“a”的长度也传递给C++,但如果是这样,我也不知道该怎么做。

+1

你是不是该数组传递给C++代码。您直接访问公共块作为外部结构。请相应地纠正你的问题。我已经改正了标题。 –

回答

2

我的Fortran生锈了一点(好的,确实有点),但让我给它一个旋风。

a可能收到了VALUE而不是指向它的指针。那会将它设置为1,这不是一个好的指针值。

b收到数据块中的第二个值。你的C++结构并没有给编译器提供什么数据的真实格式,所以它会按照结构中给出的顺序无意识地将项目分配给结构。我会得到一个指向数据块的指针并手工分解它。

a指定给数据块的地址(作为long int指针,看起来像;您的里程可能会有所不同)和b = a[5]。希望有所帮助。

+0

OOPS;可能应该是一个int指针(对不起)。如果分配正确,则[1]应该为5. – JoeBuddha

+0

关闭时,他没有收到任何“按值”,而是在“COMMON”块中,数据按顺序排列并且是连续的。基本上,COMMON块中数组的C/C++结构等价于一个平面数组。 – user7116

+0

是的,如果它是“按价值”,它会有所不同。他得到的是数据块的地址。把它与整数数组分开仍然是我的工作;然而,我懒得摆弄映射。另外,我最后的Fortran程序是在70年代写成的。 ;) – JoeBuddha

3

我看来像你的FORTRAN数据实际布局为

struct { 
    int a[5]; 
    int b; 
} 

,你是一台机器,其中sizeof(int) == sizeof(int*)上。

+0

+1,“COMMON”块的成员通常(不会混淆编译器选项)在内存中按顺序排列。因此,当给定'COMMON'块'SAMPLE'的起始地址时,数组'A'将与'B'连续。 – user7116

+1

应该注意数据的对齐。默认情况下,Fortran编译器不会将具有填充的COMMON块成员对齐,但如果提供了主动优化选项,则该成员可能会更改。因此,必须确保C/C++结构具有相同的字段对齐方式,如果在Fortran方面使用了优化方法。 –

6

如果要在C和Fortran之间共享全局变量,最好的方法是使用模块变量和Fortran ISO_C_Binding。公用块是遗留的,除非遗留代码的一部分,否则最好避免。使用ISO_C_Binding将使您的代码编译器和平台无关。在gfortran手册的“混合语言编程”一章的“互操作性全局变量”小节中有一个代码示例。这不是特定于gfortran,只是一些很好的文档。

继续使用ISO_C_Binding,如果使用它提供的Fortran类型,将确保与C类型匹配。 Fortran相当于C的intC_INT。列表显示在gfortran手册的“内在模块”一章中。

+2

不幸的是,有数以百万计的FORTRAN 77代码遗迹,并不总是可以在Fortran 2003中重写它。 –

+0

我并不反对这个,但是呃,它以相当谨慎的方式回答了horstmann的问题。 – user7116

0

thak你都为你有用的肛门。根据你的建议,我终于意识到我的问题是什么。我觉得我的错误是,Fortran中我有:

integer a(5),b 
common /sample/ a,b 

a(5)有一个固定的大小,然后在C++:

extern "C"{ 
    extern struct{ 
     int *a,b; 
}sample_; 

*a没有大小,作为一个指针。因此,编译器是这样理解的,因为*int指针代替a(5)指针

+0

欢迎来到StackOverflow!鉴于他们的答案解决了您的问题,您应该接受[Christopher's](http://stackoverflow.com/a/10482608/7116)或[Joe's](http://stackoverflow.com/a/10482194/7116)回答。您可以点击旁边的复选标记来完成此操作。 – user7116