我必须在mex文件中使用mxCalloc函数而不是常规分配,以避免matlab在使用dgesv时崩溃。 我尝试了很多方法,但没有一个方法奏效。 这是其中一个样本
#include "fintrf.h"
C Gateway subroutine
subroutine mexfunction(nlhs, plhs, nrhs, prhs)
C Declarations
implicit none
C mexFunction arguments:
mwPointer plhs(*), prhs(*)
integer nlhs, nrhs
C Function declarations:
mwPointer mxGetPr
mwPointer mxCreateDoubleMatrix
mwPointer mxGetM
C Pointers to input/output mxArrays:
mwPointer pr_A, pr_B
C Array information:
mwPointer sizea,mxCalloc
real*8 :: A,B
character*120 :: line
C Get the size of the input array.
sizea = mxGetM(prhs(1))
A=mxCalloc(sizea*sizea,8)
B=mxCalloc(sizea*sizea,8)
C Create Fortran array from the input argument.
pr_A = mxGetPr(prhs(1))
call mxCopyPtrToReal8(pr_A,A,sizea**2)
C Create matrix for the return argument.
plhs(1) = mxCreateDoubleMatrix(sizea, sizea, 0)
pr_B = mxGetPr(plhs(1))
write(line,*), sizea
call mexPrintf(line)
B=A
call mxCopyReal8ToPtr(B,pr_B,sizea*sizea)
return
end
当我运行此代码时,我得到以下结果
A = [0.9575,0.1576; 0.9649,0.9706]
测试(A)= [0.9575,0; 0.9649,0]
但如果我改变了这条线
call mxCopyReal8ToPtr(B,pr_B,sizea*sizea)
到
call mxCopyReal8ToPtr(A,pr_B,sizea*sizea)
,
结果是正确的
变量sizea等于2这是正确的,但是我无法访问A的任何成员,比如说A(1,1),并且我遇到了错误:
错误#6410:此名称尚未声明为数组或a 功能。 [A]
答案 0 :(得分:3)
代码中的A被声明为单个变量,但是大小(A,1)正在尝试访问它,就像它是一个数组一样。您必须明确告诉Fortran A具有数组的形状。在快速浏览一下其余的代码后,我假设A和B应该是2维
real*8 :: A(:,:),B(:,:)
现在我不太了解mxCalloc的工作原理以及它如何处理内存分配以及与Fortran的接口,但可能还需要将A和B声明为指针。
real*8, pointer :: A(:,:),B(:,:)
答案 1 :(得分:3)
(免责声明:我没有使用Mex的经验,因此请采用以下代码......)
这是@ftiaronsem和Dave之前one的答案的延续。通过查看此tutorial,在mxCalloc()
中使用Fortran可分配数组似乎没问题。但是,OP的目的是使用mxCalloc()
而不是可分配的数组进行内存管理。
根据Matlab的在线手册,mwpointer
似乎将分配的内存地址返回为integer*8
(这只是64位计算机上mwpointer iA
iA = mxCalloc( sizea * sizea, 8 )
的别名,到头文件fintrf.h
)。所以,我们首先得到地址为
B
(同样适用于iA
)。接下来,我们想要从type(c_ptr)
开始作为2-d Fortran阵列访问内存。这可以通过使用c_f_pointer()(在F2003中)来完成。但是,由于此函数的第一个参数接收use iso_c_binding
type(c_ptr) cA
real*8, pointer :: A(:,:)
cA = transfer( iA, cA ) !! cast integer*8 to c_ptr
call c_f_pointer( cA, A, [ sizea, sizea ] ) !! init an array pointer with c_ptr
,我们按如下方式进行:
A
在此语句之后,我们可以使用#include "fintrf.h"
C Gateway subroutine
subroutine mexfunction(nlhs, plhs, nrhs, prhs)
use iso_c_binding !<---
C Declarations
implicit none
C mexFunction arguments:
mwPointer plhs(*), prhs(*)
integer nlhs, nrhs
C Function declarations:
mwPointer mxGetPr
mwPointer mxCreateDoubleMatrix
mwsize mxGetM, sizea !<--- changed to mwsize (may not be necessary, though)
C Pointers to input/output mxArrays:
mwPointer pr_A, pr_B
C Array information:
mwPointer mxCalloc
mwPointer :: iA, iB !<---
type(c_ptr) :: cA, cB !<---
real*8, pointer :: A(:,:), B(:,:) !<---
character*120 :: line
C Get the size of the input array.
sizea = mxGetM(prhs(1))
iA = mxCalloc( sizea**2, 8 ) !<---
iB = mxCalloc( sizea**2, 8 ) !<---
cA = transfer( iA, cA ) !<---
cB = transfer( iB, cB ) !<---
call c_f_pointer( cA, A, [ nsizea, nsizea ] ) !<---
call c_f_pointer( cB, B, [ nsizea, nsizea ] ) !<---
C Create Fortran array from the input argument.
pr_A = mxGetPr(prhs(1))
call mxCopyPtrToReal8( pr_A, A, sizea**2 )
C Create matrix for the return argument.
plhs(1) = mxCreateDoubleMatrix(sizea, sizea, 0)
pr_B = mxGetPr(plhs(1))
write(line,*), sizea
call mexPrintf(line)
B = A
call mxCopyReal8ToPtr( B, pr_B, sizea**2 )
!! may need to call mxFree( iA ) and mxFree( iB ) manually?
!! (or Matlab may automatically do it upon exit)
return
end
作为普通的2-d Fortran数组(例如,我们可以将它传递给LAPACK例程)。将这些修改包括在OP代码中给出了以下内容。那么你可以尝试一下,看它是否有效......?
更新的代码(ver1):
def main():
endProgram = "no"
#at the end the program will ask the user if the want to stop
#if the say yes the program will end if they say no the will
#cause the program to rerun
while endProgram == "no":
notGreenCost = [11]
goneGreenCost = [11]
savings = [11]
months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
#function calls
notGreenCosts[12] = getNotGreen(notGreenCost, months)
getGoneGreen(goneGreenCost, months)
energySaved(notGreenCost, goneGreenCost, savings)
displayInfo(notGreenCost, goneGreenCost, savings, months)
endProgram = str(input("Do you want to end the program? yes or no"))
def getNotGreen(notGreenCost, months):
counter = 0
while counter < 11:
print("Enter GONE GREEN energy costs for", months[counter])
notGreenCost[index] = int(input(":"))
counter = counter + 1
return notGreenCost
main()