Fortran Coder

查看: 15702|回复: 14
打印 上一主题 下一主题

[混编] c++向Fortran的dll传递字符串发生“访问冲突”

[复制链接]

1963

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1357 元
贡献
574 点

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

楼主
发表于 2016-11-4 08:48:39 | 显示全部楼层
subroutine vlhm( pfilename , lens ) Bind(C,Name="vlhm")
!!!subroutine vlhm(pfilename,lens) Bind(C,Name="vlhm@8")
!DEC$ ATTRIBUTES stdcall , DLLEXPORT::vlhm
  use ,Intrinsic::ISO_C_Binding
  implicit none
  type(C_PTR) , value :: pfilename !c++主程序中传递进来的“Inputfile”变量,是C语言的指针
  integer ,value ::lens                                      !传入的字符串长度
  character(len=lens),pointer::filename                     !这是Fortran的字符串
  call c_f_pointer( pfilename , filename )                   !把c语言的指针转换成fortran字符串
  write(*,*)filename
end subroutine

注意上面红色的部分。
第一处:如果你强调必须 stdcall 协定,那么你需要在 fortran 中声明。(这个声明不是规范的,是IVF扩展的写法)
第二处:你的 C++ 里的 lens 是通过 strlen 计算出来的,而不是指针。所以 fortran 中必须加 value 修饰符,表示它是传值,而不是传址。(这是导致
  cpp_main.exe 中的 0x5d7005a9 (vlhm.dll) 处最可能的异常: 0xC0000005: 读取位置 0x00000021 时发生访问冲突)的原因。
  因为编译器错误的把 Lens=33 这个值(即十六进制的 0x00000021)当成了地址(读取这个低位的地址就会失败)

1963

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1357 元
贡献
574 点

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

沙发
发表于 2016-11-4 09:26:57 | 显示全部楼层
可能你的 IVF 版本有些老,支持得还不全面。
那你只能这样写了:
[Fortran] 纯文本查看 复制代码
subroutine vlhm( pfilename , lens )
!DEC$ ATTRIBUTES stdcall , alias: '_vlhm@8' , DLLEXPORT::vlhm


去掉 Bind(C ,Name="vlhm")
然后 ATTRIBUTES 里面写 stdcall 和 alias

1963

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1357 元
贡献
574 点

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

板凳
发表于 2016-11-14 22:44:27 | 显示全部楼层
看 5 楼
回复

使用道具 举报

1963

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1357 元
贡献
574 点

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

地板
发表于 2016-11-15 23:03:08 | 显示全部楼层
1. 你不能全部照抄别人的例子,例如这个例子,是因为提问者的“甲方”要求,必须使用 stdcall。
2. 而 ISO_C_Binding 只能用“规范的语言”写 c 的调用协定,而不能写 stdcall 调用协定。
3. 因此,这个例子的提问者没有办法,只能使用 ATTRIBUTES 来实现 stdcall
4. 如果你只是要和 C 进行混编,而没有“必须使用 stdcall”的要求。那么 Bind( C 就可以实现
5. 我对IVF各个版本具体支持什么扩展特性并不十分清楚。毕竟我用过的也就那么一两个版本,而不会每个版本都用。
6. 去掉 Bind(C 的话,会有两个影响:
   a. 不能默认 c调用协定,而使用 IVF协定(当然你可以用 ATTRIBUTES 更改协定,只不过低版本的IVF不允许 Bind C 和 ATTRIBUTES并存,因为两者冲突)
   b. 不能默认 c的“符号修饰”(比如 name(x) 被修饰为 _name@4 或者 _name),相当于 Alias。
   除了上面两个差别,Bind( C )没有其他作用。关于参数传递约定,数组/字符串传递,请遵循 ISO_C_Binding 约定。

其实混编就那么点东西
Bind(C 是规范的,用来起到默认 C 协定,及默认 C 符号修饰的目的。
而 ATTRIBUTES 和 ALIAS 是扩展语法。作用其实与 Bind C 一样。
区别,仅仅是规范和不规范而已。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

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

GMT+8, 2024-5-7 10:46

Powered by Tencent X3.4

© 2013-2024 Tencent

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