Fortran Coder

查看: 19863|回复: 17
打印 上一主题 下一主题

[混编] 求助:关于iso_c_binding中C端多重指针参数接口的写法

[复制链接]

125

帖子

33

主题

0

精华

宗师

F 币
1574 元
贡献
800 点
跳转到指定楼层
楼主
发表于 2021-7-29 16:01:53 | 只看该作者 |只看大图 回帖奖励 |正序浏览 |阅读模式

求教一个混编问题:

我要调用一个C语言函数:
[C] 纯文本查看 复制代码
int get_table(char ***Results );

这个函数位于一个已经封装好的动态链接库中,作用是读取一个文件,将内容存储到二维字符串数组Results中。

按照如下写法,我得到的Results是一个乱码:

接口:
[Fortran] 纯文本查看 复制代码
interface
  function get_table(Results) bind(c)
    use iso_c_binding, only: c_int, c_char
    character(kind=c_char),dimension(*)::Results
    integer(c_int):: get_table
  end function
end interface


调用:

[Fortran] 纯文本查看 复制代码
character(8) :: Results(3,10)
i =  get_table(Results)


结果:
                Results(1,1)        '鴴+     '        CHARACTER(8)
                Results(2,1)        '        '        CHARACTER(8)
                Results(3,1)        '        '        CHARACTER(8)
                Results(1,2)        '        '        CHARACTER(8)
                Results(2,2)        '        '        CHARACTER(8)
                Results(3,2)        '        '        CHARACTER(8)
                Results(1,3)        '        '        CHARACTER(8)
                Results(2,3)        '        '        CHARACTER(8)
                Results(3,3)        '        '        CHARACTER(8)
                Results(1,4)        '        '        CHARACTER(8)

……
……
这个结果并不是我预期的。

请教大神,这个interface应该如何写,Fortran中的Results参数应该如何声明?
先谢过!


分享到:  微信微信
收藏收藏1 点赞点赞 点踩点踩

125

帖子

33

主题

0

精华

宗师

F 币
1574 元
贡献
800 点
18#
 楼主| 发表于 2021-8-23 09:58:04 | 只看该作者
fcode 发表于 2021-8-20 19:29
function sqlite3_reset(stmt) bind(c)
       import
       type(c_ptr), value :: stmt

之前百度了一个答案说是新版中sqlite3_step已经包含了sqlite3_reset,所以我给去掉了……
现在加上就好了,非常感谢!

再次感谢二位这段时间不厌其烦的帮助!

2022

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1598 元
贡献
689 点

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

17#
发表于 2021-8-20 19:29:11 | 只看该作者
     function sqlite3_reset(stmt) bind(c)
       import
       type(c_ptr), value :: stmt
       integer(c_int) sqlite3_reset
     end function sqlite3_reset


    istat = sqlite3_step(stmt)
    write(*,"(A,I0,A,I0)") "第",i,"次sqlite3_step返回",istat
    istat = sqlite3_reset(stmt)

125

帖子

33

主题

0

精华

宗师

F 币
1574 元
贡献
800 点
16#
 楼主| 发表于 2021-8-20 10:09:37 | 只看该作者
fcode 发表于 2021-8-19 13:07
sqlite3_bind_text 的时候,并没有写入,只是存入地址。
等到 sqlite3_step 的时候,才会真正写入。
因为你 ...

谢谢!这个点明白了!但是运行之后还是有些问题,是不是sqlite3_bind_text的接口/参数还是存在问题呢?见图片:

20210820100251.png (68.21 KB, 下载次数: 358)

20210820100251.png

FortranCallC.rar

805 Bytes, 下载次数: 3

2022

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1598 元
贡献
689 点

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

15#
发表于 2021-8-19 13:07:30 | 只看该作者
sqlite3_bind_text 的时候,并没有写入,只是存入地址。
等到 sqlite3_step 的时候,才会真正写入。
因为你都是用的 s_data 这个变量,所以地址相同。
最后,所有的值,都是最后一次的值

125

帖子

33

主题

0

精华

宗师

F 币
1574 元
贡献
800 点
14#
 楼主| 发表于 2021-8-19 11:33:34 | 只看该作者
fcode 发表于 2021-8-18 11:06
sss = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"c
istat = sqlite3_bind_text(stmt, 1, sss, 32, c_null_ptr);

谢谢老群主!但是,奇怪的现象又来了……明明赋了不同的值,居然写进去两个同样的值……

20210819105733.png (55.71 KB, 下载次数: 385)

20210819105733.png

2022

帖子

12

主题

5

精华

论坛跑堂

臭石头雪球

F 币
1598 元
贡献
689 点

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

13#
发表于 2021-8-18 11:06:26 | 只看该作者
sss = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"c
istat = sqlite3_bind_text(stmt, 1, sss, 32, c_null_ptr);

这样就可以了。此处sss只能是引用,不能是表达式。
因为给 C 语言的是一个指针,而表达式结果是临时存放的,一旦整个语句结束,表达式的结果就清空了。
你试试,这样都不行:
istat = sqlite3_bind_text(stmt, 1, (sss), 32, c_null_ptr);
因为 (sss) 也是一个表达式。

125

帖子

33

主题

0

精华

宗师

F 币
1574 元
贡献
800 点
12#
 楼主| 发表于 2021-8-18 09:56:01 | 只看该作者
本帖最后由 andy8496 于 2021-8-18 10:20 编辑
布衣龙共 发表于 2021-8-16 16:14
原来是 sqlite。sqlite3_get_table 的参数,你给他一个指针,由它内部分配空间,最后把它分配的空间的地址 ...

非常不好意思,又遇到一个问题。


在7#楼附件工程DB_Test/FortranCallC/Source Files/FortranCallC.f90中,生成数据文件的部分:

[Fortran] 纯文本查看 复制代码
  istat = sqlite3_open(trim(filename)//""C, db)
  sql = "CREATE TABLE MY_TABLE (ID INTEGER PRIMARY KEY  AUTOINCREMENT, "// &
            "DATA1           TEXT    NOT NULL, " // &
            "DATA2           TEXT )"
  istat = sqlite3_exec(db, sql, c_null_funptr, c_null_ptr, ErrMsg)
  istat = sqlite3_exec(db,"begin;",c_null_funptr, c_null_ptr, ErrMsg)
  sql = "INSERT INTO MY_TABLE (DATA1,DATA2) VALUES (?,?);"C
  istat = sqlite3_prepare_v2(db,sql,len_trim(sql),stmt,c_null_ptr)
  do i=1,50
   istat = sqlite3_bind_text(stmt, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 32, c_null_ptr);
   istat = sqlite3_bind_text(stmt, 2, "0123456789", 16, c_null_ptr);
    istat = sqlite3_step(stmt)
  enddo
istat = sqlite3_finalize(stmt)
istat = sqlite3_exec(db,"commit;",c_null_funptr, c_null_ptr, ErrMsg)
  istat = sqlite3_close(db)


如果在sqlite3_bind_text中像上文那样直接用字符串常量就没问题:
[Fortran] 纯文本查看 复制代码
istat = sqlite3_bind_text(stmt, 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 32, c_null_ptr);

但是改成变量写进去的就是乱码,读出来的也是乱码了
[Fortran] 纯文本查看 复制代码
 sss = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”  ! character(256) :: sss
istat = sqlite3_bind_text(stmt, 1, trim(sss)//""C 32, c_null_ptr);



能想到的原因有两个:
①字符串声明的有问题,或者类型不合适
②可能与编码有关
做了一些尝试,问题依旧。无奈再次求助!

125

帖子

33

主题

0

精华

宗师

F 币
1574 元
贡献
800 点
11#
 楼主| 发表于 2021-8-17 09:00:31 | 只看该作者
布衣龙共 发表于 2021-8-16 17:44
可以,没关系的。

Fortran 的指针不需要释放,C那边你找找,可能有别的函数来释放。 ...

Perfect!再次感谢!!!

54

帖子

0

主题

0

精华

实习版主

F 币
653 元
贡献
214 点

元老勋章新人勋章

QQ
10#
发表于 2021-8-16 17:44:23 | 只看该作者
可以,没关系的。

Fortran 的指针不需要释放,C那边你找找,可能有别的函数来释放。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

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

GMT+8, 2024-11-23 13:49

Powered by Tencent X3.4

© 2013-2024 Tencent

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