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

时间:2016-07-05 05:43:32

标签: arrays lua fortran lua-table

我正在寻找Fortran示例(也是接口函数)将数组作为参数传递给lua函数。我能够使用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

1 个答案:

答案 0 :(得分:1)

为了扩展我的评论,这是一个在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表。看看它的代码,看看如何将数据放入表中。

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

 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函数print_array写入以Lua开头的两行。

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