Fortran Coder

查看: 6658|回复: 3
打印 上一主题 下一主题

[指针] 如何将下列函数改写成fortran程序

[复制链接]

13

帖子

8

主题

0

精华

入门

F 币
83 元
贡献
51 点
跳转到指定楼层
楼主
发表于 2016-1-15 15:10:02 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
现在我是想使用fortran写这个函数,写为fortran后,再调用c中的一个函数,将这个改写的fortran子程序的地址传递给c函数。
[C] 纯文本查看 复制代码
void my_neighbors(void** neighbor_addrs,int* num_neigh, targs* args)
{
    int starti=args->starti;
    int startj=args->startj;
    void* src_addr=args->src_addr;

    *num_neigh=0;
    if(starti - BLKX>=0)
      neighbor_addrs[(*num_neigh)++]=(void*)(src_addr - BLKX * SIZEY * SIZEZ * 8);
    if(starti + BLKX < SIZEX)
        neighbor_addrs[(*num_neigh)++]=(void*)(src_addr + BLKX * SIZEY * SIZEZ * 8);
    if(startj - BLKY >= 0)
        neighbor_addrs[(*num_neigh)++]=(void*)(src_addr - BLKY * SIZEZ * 8);
    if(startj + BLKY < SIZEY)
        neighbor_addrs[(*num_neigh)++]=(void*)(src_addr + BLKY * SIZEZ* 8);
}

群主告诉我在fortran中没有类似void类型。那改成integer,即integer,dimension(:),pointer :: neighbor_addrs.改成指针数组后,我知道有一个库函数loc()可以获得对象地址。但是如果改成integer会不会造成信息丢失?
neighbor_addrs[(*num_neigh)++]=(void*)(src_addr - BLKX * SIZEY * SIZEZ * 8);改写方式我是这样想的,如下: 前面已经改成了integer类型。
integer loc
neighbor_addrs => loc(src_addr - BLKX * SIZEY * SIZEZ * 8 不知道我改写的对不对?我实际上想希望这条语句改写可以想原来语句似得。可以
neighbor_addrs(num_neigh) = locsrc_addr - BLKX * SIZEY * SIZEZ * 8).
具体如何改写,请大家教教我。
分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

2033

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1641 元
贡献
709 点

美女勋章热心勋章星光勋章新人勋章贡献勋章管理勋章帅哥勋章爱心勋章规矩勋章元老勋章水王勋章

沙发
发表于 2016-1-15 18:35:01 | 只看该作者
1. Fortran 和 C 语言的指针完全是两回事。你不能在fortran里混合使用他们。
2. loc函数是不标准的写法,只是部分编译器的扩展,不建议使用。
3. loc函数获得的,是内存地址。但fortran的指针远不止地址。所以绝对不能 => loc()
4. 你不能习惯性的把C语言的想法放在fortran里。C语言的指针就是地址,但fortran不是。
  fortran的指针,除了地址之外,还包括但不限于数组的大小,维度,每个维度的上下限,间距等。
5. C严格的说,不是高级语言,而是中级语言。或者是偏低级的高级语言。而 Fortran 是完全的高级语言。
  这里说的高级低级,是指更偏向计算机底层,还是更偏向于人类习惯。而不是指谁更牛。
6. C语言灵活。Fortran语言严谨。比如,fortran的指针包含了目标的概要描述,因此更安全,不容易指歪。
  相比而言,C语言的指针只是地址,很容易出现不可控。(当然,程序员良好的习惯可以避免)
7. Fortran 里,没有“指针数组”,只有“指向数组的指针”,也没有“指向指针的指针”。
8. 由于 Fortran 语言更严谨。所以,它很难容许不确定数据类型,不确定数组大小范围的情况。你必须确定以下内容:
  a. neighbor_addrs 指向的内容是什么类型?
  b. args->src_addr 指向的内容是什么类型?
  c. neighbor_addrs 这个指针数组有多大?
9. 如果你确定了这些问题,我可以尝试帮助你修改你的代码。

13

帖子

8

主题

0

精华

入门

F 币
83 元
贡献
51 点
板凳
 楼主| 发表于 2016-1-16 16:08:13 | 只看该作者
本帖最后由 苏坡,man 于 2016-1-16 16:14 编辑

a. neighbor_addrs 指向的内容是指定的是 在c中void**类型
b. args->src_addr 指向的内容是void*
c. neighbor_addrs 这个指针数组有256大小
我今天将这个void my_neighbors(void** neighbor_addrs,int* num_neigh, targs* args)进行了改写,改写如下:
subroutine neighbor(neighbor_addrs,num_neigh,args)
28           implicit none
29           include 'global.h'
30           integer(c_int),pointer :: neighor_addrs !改成整形的指针
31           integer(c_int),pointer :: num_neigh
32           integer(c_int) num
33           class(struct),pointer :: args
34           integer(c_int) starti,startj
35           integer(c_int),pointer :: src  !也写成了整形指针
36              starti = args%starti
37              startj = args%startj
38              src => args%src_addr
39              num = 0
40         
41           if (starti>=BLKX)then
42              neighbor_addrs=>c_loc(src-BLKX*BLKY*Z*8)
43              num=num+1
44             num_neigh=>num  !num_neigh实际上是计数用的
45           endif
46           if (starti<X-BLKX)then
47              neighbor_addrs=>c_loc(src+BLKX*BLKY*Z*8) !这个c_loc是不是应该写为loc,或者说不需要使用c_loc,直接赋值给neighbor_addrs
48              num=num+1
49              num_neigh=>num
50           endif
51           if (startj>=BLKY)then
52              neighbor_addrs=>c_loc(src-BLKY*Z*8)
53              num=num+1
54              num_neigh=>num
55           endif
56           if (startj<Y-BLKY)then
57              neighbor_addrs=>c_loc(src+BLKY*Z*8)
58              num=num+1
59              num_neigh=>num
60           endif
61          end subroutine neighbor
这个函数最后也是要传递给系统中c的函数,在系统中使用的 neighbor_addrs类型仍然是void**,num_neigh是int*,src_addr是void*
原先的c程序的代码如下:原先c程序代码改写fortran语言编写。
typedef struct{
  int starti, endi;
  int startj, endj;
  int k_N;
  int iter;
void* src_addr;
}targs;
void my_neighbors(void** neighbor_addrs,int* num_neigh, targs* args)
{
    int starti=args->starti;
    int startj=args->startj;
    void* src_addr=args->src_addr;
  
    *num_neigh=0;
    if(starti - BLKX>=0)
        neighbor_addrs[(*num_neigh)++]=(void*)(src_addr - BLKX * SIZEY * SIZEZ * 8);
    if(starti + BLKX < SIZEX)
        neighbor_addrs[(*num_neigh)++]=(void*)(src_addr + BLKX * SIZEY * SIZEZ * 8);
    if(startj - BLKY >= 0)
        neighbor_addrs[(*num_neigh)++]=(void*)(src_addr - BLKY * SIZEZ * 8);
    if(startj + BLKY < SIZEY)
        neighbor_addrs[(*num_neigh)++]=(void*)(src_addr + BLKY * SIZEZ* 8);
}

490

帖子

4

主题

0

精华

大宗师

F 币
3298 元
贡献
1948 点

水王勋章元老勋章热心勋章

地板
发表于 2016-1-16 19:50:49 | 只看该作者
现在我是想使用fortran写这个函数,写为fortran后,再调用c中的一个函数,将这个改写的fortran子程序的地址传递给c函数。

用gfortran的话,参考
https://gcc.gnu.org/onlinedocs/g ... rking-with-Pointers
If a pointer is a dummy-argument of an interoperable procedure, it usually has to be declared using the VALUE attribute. void* matches TYPE(C_PTR), VALUE, while TYPE(C_PTR) alone matches void**.

现成的例子都有,之前也贴过了,lz估计日理万机,也就无暇他顾了。。。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-12-25 10:07

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表