将数组作为函数参数从 Fortran 传递给 lua

Passing arrays to lua as function argument from Fortran

我正在寻找将数组作为参数传递给 lua 函数的 Fortran 示例(也是接口函数)。我能够使用 fortlua project 开始。但是提供的示例一次传递一个元素。感谢任何帮助。

--Lua code 

local q1
local q2
function getoutput( qout1, qout2)
-- qout1 and qout2 are arrays with some dimension
  q1 = qout1
  q2 = qout2
end

-- 在 fortran 中我使用

config_function('getoutput', args, 2, cstatus)

但是设置 args 是我寻求帮助的地方。下面的代码完成了标量参数变量的工作,我猜不是数组。

!> Evaluate a function in the config file and get its result.
FUNCTION config_function(name,args,nargs,status)
    REAL :: config_function
    CHARACTER(LEN=*) :: name
    REAL, DIMENSION(nargs) :: args
    REAL(KIND=c_double) :: anarg
    INTEGER :: nargs
    INTEGER :: status
    INTEGER :: iargs
    INTEGER(c_int) :: stackstart

    stackstart = lua_gettop(mluastate)

    config_function = 0
    status = 0


    CALL lua_getglobal(mluastate,TRIM(name)//C_NULL_CHAR)
    IF ( lua_type(mluastate,-1) .eq. LUA_TFUNCTION ) THEN
        DO iargs = 1,nargs
          anarg = args(iargs)
          CALL lua_pushnumber(mluastate,anarg)
        ENDDO
        IF (lua_pcall(mluastate,nargs,1,0) .eq. 0) THEN
          if (lua_isnumber(mluastate,-1) .ne. 0) THEN
            config_function = lua_tonumber(mluastate,-1)
            CALL lua_settop(mluastate,-2)
          ELSE
            ! Nothing to pop here
            status=-3
          ENDIF
        ELSE
          CALL lua_settop(mluastate,-2)
          status=-2
        ENDIF
    ELSE
        CALL lua_settop(mluastate,-2)
        status=-1
    ENDIF
    IF (stackstart .ne. lua_gettop(mluastate)) THEN
       WRITE(*,*) 'The stack is a different size coming out of config_function'
    ENDIF
END FUNCTION config_function

为了扩展我的评论,这是一个在 Aotus 的帮助下实现数组参数的小程序:

program aot_vecarg_test
  use flu_binding, only: flu_State, flu_settop

  use aotus_module, only: open_config_file, close_config
  use aot_fun_module, only: aot_fun_type, aot_fun_do, &
    &                       aot_fun_put, aot_fun_open, &
    &                       aot_fun_close
  use aot_references_module, only: aot_reference_for, aot_reference_to_top
  use aot_table_module, only: aot_table_open, aot_table_close, &
    &                         aot_table_from_1Darray

  implicit none

  type(flu_State) :: conf
  type(aot_fun_type) :: luafun
  integer :: iError
  character(len=80) :: ErrString
  real :: args(2)
  integer :: argref
  integer :: arghandle

  args(1) = 1.0
  args(2) = 2.0

  call create_script('aot_vecarg_test_config.lua')
  write(*,*)
  write(*,*) 'Running aot_vecarg_test...'
  write(*,*) ' * open_config_file (aot_vecarg_test_config.lua)'
  call open_config_file(L = conf, filename = 'aot_vecarg_test_config.lua', &
    &                   ErrCode = iError, ErrString = ErrString)
  if (iError /= 0) then
    write(*,*) ' : unexpected FATAL Error occured !!!'
    write(*,*) ' : Could not open the config file aot_ref_test_config.lua:'
    write(*,*) trim(ErrString)
    STOP
  end if
  write(*,*) '  : success.'

  ! Create a table with data
  call aot_table_from_1Darray( L       = conf,      &
    &                          thandle = arghandle, &
    &                          val     = args       )
  ! Create a reference to this table
  call flu_setTop(L = conf, n = arghandle)
  argref = aot_reference_for(L = conf)

  ! Start the processing of the function
  call aot_fun_open(L = conf, fun = luafun, key = 'print_array')
  ! Put the previously defined table onto the stack by using the reference
  call aot_reference_to_top(L = conf, ref = argref)
  ! Put the top of the stack to the argument list of the Lua function
  call aot_fun_put(L = conf, fun = luafun)
  ! Execute the Lua function
  call aot_fun_do(L = conf, fun = luafun, nresults = 0)
  call aot_fun_close(L = conf, fun = luafun)

  write(*,*) ' * close_conf'
  call close_config(conf)
  write(*,*) '  : success.'
  write(*,*) '... Done with aot_vecarg_test.'
  write(*,*) 'PASSED'

contains

  subroutine create_script(filename)
    character(len=*) :: filename

    open(file=trim(filename), unit=22, action='write', status='replace')
    write(22,*) '-- test script for vectorial argument'
    write(22,*) 'function print_array(x)'
    write(22,*) '  for i, num in ipairs(x) do'
    write(22,*) '    print("Lua:"..num)'
    write(22,*) '  end'
    write(22,*) 'end'
    close(22)
  end subroutine create_script

end program aot_vecarg_test

这利用了一个小帮助例程 aot_table_from_1Darray 为实数数组创建 Lua table。查看它的代码,了解如何将数据放入 table.

然后我们创建对此 table 的引用以便稍后轻松查找并将其作为参数传递给 Lua 函数。 该示例创建了相应的 Lua 脚本本身,它定义了一个简单的函数,该函数期望将单个 table 作为输入并打印每个 table 条目。 运行 这会产生以下输出:

 Running aot_vecarg_test...
  * open_config_file (aot_vecarg_test_config.lua)
   : success.
Lua:1.0
Lua:2.0
  * close_conf
   : success.
 ... Done with aot_vecarg_test.
 PASSED

其中Lua开头的两行是Lua函数写的print_array.

还有其他可能的解决方案,但我希望这至少可以让您了解如何做到这一点。我们还可以考虑扩展 aot_fun_put 接口来处理数组本身。