fortran generates dll for python call

 

The Fortran(90) code is as follows:

!  fortranDLLExample.f90 
!
!  FUNCTIONS/SUBROUTINES exported from fortranDLLExample.dll:
!  fortranDLLExample - subroutine 

FUNCTION ABZERO(P) bind(C,name="ABZERO")
    !DEC$ ATTRIBUTES DLLEXPORT :: ABZERO
    !DEC$ ATTRIBUTES VALUE :: P
    integer, INTENT(IN) :: P   
    integer :: ABZERO
    integer :: result1
    ! Examle calculation
    result1 = P - 273
    print *, "The p==", P, ";"
    print *, "The p-273 [", result1, "]"
    ABZERO = result1
    RETURN 
END FUNCTION

FUNCTION ABZERO_FLOAT(P) bind(C,name="ABZERO_FLOAT")
    !DEC$ ATTRIBUTES DLLEXPORT :: ABZERO_FLOAT
    !DEC$ ATTRIBUTES VALUE :: P
    real, INTENT(IN) :: P   
    real :: ABZERO_FLOAT
    real :: result1
    ! Examle calculation
    result1 = P - 273.15
    print *, "The p==", P, ";"
    print *, "The p-273 [", result1, "]"
    ABZERO_FLOAT = P - 273.15
    RETURN 
END FUNCTION

FUNCTION sum(length1, P) bind(C,name="sum")
    !DEC$ ATTRIBUTES DLLEXPORT :: sum
    implicit none
    integer::length1
    real, dimension(*):: P
    real :: sum
    integer::i
    
    print *, "The length1==", length1, ";"
    sum =0.0
    do i = 1,length1 ! sum the array elements
        sum = sum + p(i)
        PRINT *,p(i)
    end do
    RETURN 
END FUNCTION

subroutine func01( a ) bind(C,name="func01")
    !DEC$ ATTRIBUTES DLLEXPORT :: func01
    implicit none
    character(len=1), dimension(90) , intent(in) :: a
    character(len=30), dimension(3) :: b
    integer*4 :: count,i,j

    count=1
    do j=1,3
        b(J)=''
        do I=1,30
            b(J)=trim(b(J))//a(count)
            count=count+1
        enddo
    enddo

    print *
    print *, "char length = ", len(b(1)), len(b(2)), len(b(3))
    print *, "raw a(1) : [", b(1), "]"
    print *, "raw a(2) : [", b(2), "]"
    print *, "raw a(3) : [", b(3), "]"
    print *, "trim     : [", trim(b(1)), "] [", trim(b(2)), "]  [", trim(b(3)), "]"
end

FUNCTION SUMANDTIMES(P, length1, Q) bind(C,name="SUMANDTIMES")
    !DEC$ ATTRIBUTES DLLEXPORT :: SUMANDTIMES
    implicit none
    integer::length1
    real, dimension(*):: P
    real :: SUMANDTIMES, Q
    integer::i
    
    print *, "The length1==", length1, ";"
    SUMANDTIMES =0.0
    do i = 1,length1 ! sum the array elements
        SUMANDTIMES = SUMANDTIMES + p(i) * Q
        PRINT *,p(i)
    end do
    RETURN 
END FUNCTION

FUNCTION array2by2(P, row, col) bind(C,name="array2by2")
    !DEC$ ATTRIBUTES DLLEXPORT :: array2by2
    USE ISO_C_BINDING
    implicit none
    integer::row, col, i, j, array2by2
    !real,DIMENSION(row*col)::
    real P(*)
    real PP(row, col)
    print *, "---->row-----", row
    print *, "---->col-----", col
    do i=1,row
        do j=1,col
            PP(i,j) = P((i-1)*row+j)
            P((i-1)*row+j) = PP(i,j) * 100
            print *, PP(i,j), i, j, (i-1)*row+j
        end do
        print *, "----row-----", i
    end do
    array2by2 = 0
    RETURN 
END FUNCTION

 

The Python calling code is as follows (dll is placed in the same directory as the py file)

# coding=utf-8

from _ctypes import byref
from ctypes import cdll, c_int, c_float
import ctypes

my_dll = cdll.LoadLibrary('fortranDLLExample.dll')
result = my_dll.ABZERO(c_int(324))
print "my_dll.ABZERO(c_int(324))==", result, type(result)


my_dll.ABZERO_FLOAT.restype = c_float  # 要设置返回值的类型,不然默认会返回int型,导致数据混乱
result = my_dll.ABZERO_FLOAT(c_float(500.44))
print "my_dll.ABZERO_FLOAT(c_float(500.44))", result, type(result)
# tip:dll.addf.argtypes = (c_float, c_float)
# addf 有两个形参,都是 float 类型。虽然也可以用数组设置,但是元祖的效率更高


FloatArray = c_float * 5
ia = FloatArray(5.32, 1.12, 7.321, 33.12, 99.3)
for i in ia:
    print i
my_dll.sum.restype = c_float
result = my_dll.sum(byref(c_int(len(ia))), byref(ia))
print "dll.sum == ", result


FloatArray = c_float * 3
ia2 = FloatArray(1.1, 2.2, 3.3)
my_dll.SUMANDTIMES.restype = c_float
result = my_dll.SUMANDTIMES(byref(ia2),
                     byref(c_int(len(ia2))),
                     byref(c_float(100.1)))
print "dll.SUMANDTIMES == ", type(result), result


# 出现win32不是有效的应用程序bug的时候,记得在fortran编辑器选择好x86或x64,版本要和python的位数对应上
d = ctypes.create_string_buffer("abcde67890b234567             "
                                "waeofijo                      "
                                "awoijewfawfe                  ", size=90)
my_dll.func01(d)


j_table = (c_float * 16)(1.1, 1.2, 1.3, 1.4,
                         2.1, 2.2, 2.3, 2.4,
                         3.1, 3.2, 3.3, 3.4,
                         4.1, 4.2, 4.3, 4.4)  # 给力
my_dll.array2by2(byref(j_table),
                 byref(c_int(4)),
                 byref(c_int(4)))
for i in j_table:
    print i,
print "--------------------- 操作完后的结果 ---------------------"


h_table = (c_float * 16)(91.1, 51.2, 1.35, 1.45,
                         92.1, 52.2, 2.35, 2.45,
                         93.1, 53.2, 3.35, 3.45,
                         94.1, 54.2, 4.35, 4.45)  # 给力
my_dll.array2by2(byref(h_table),
                 byref(c_int(4)),
                 byref(c_int(4)))
for i in h_table:
    print i,
print "--------------------- 操作完后的结果 ---------------------"


my_dll.array2by2(byref(j_table),
                 byref(c_int(4)),
                 byref(c_int(4)))
for i in j_table:
    print i,
print "默认传给dll的是指针,因此在fortran中如果动了地址里面的内容,那么反映到python上也会跟着改变"

 

The output is as follows:

 The p==         324 ;
 The p-273 [          51 ]
my_dll.ABZERO(c_int(324))== 51 <type 'int'>
 The p==   500.4400     ;
 The p-273 [   227.2900     ]
my_dll.ABZERO_FLOAT(c_float(500.44)) 227.290008545 <type 'float'>
5.32000017166
1.12000000477
7.32100009918
33.1199989319
99.3000030518
 The length1==           5 ;
   5.320000    
   1.120000    
   7.321000    
   33.12000    
   99.30000    
dll.sum ==  146.180999756
 The length1==           3 ;
   1.100000    
   2.200000    
   3.300000    
dll.SUMANDTIMES ==  <type 'float'> 660.66003418
 
 char length =           30          30          30
 raw a(1) : [abcde67890b234567             ]
 raw a(2) : [waeofijo                      ]
 raw a(3) : [awoijewfawfe                  ]
 trim     : [abcde67890b234567] [waeofijo]  [awoijewfawfe]
 ---->row-----           4
 ---->col-----           4
   1.100000               1           1           1
   1.200000               1           2           2
   1.300000               1           3           3
   1.400000               1           4           4
 ----row-----           1
   2.100000               2           1           5
   2.200000               2           2           6
   2.300000               2           3           7
   2.400000               2           4           8
 ----row-----           2
   3.100000               3           1           9
   3.200000               3           2          10
   3.300000               3           3          11
   3.400000               3           4          12
 ----row-----           3
   4.100000               4           1          13
   4.200000               4           2          14
   4.300000               4           3          15
   4.400000               4           4          16
 ----row-----           4
110.0 120.000007629 130.0 140.0 209.999984741 220.0 230.0 240.000015259 310.0 320.0 330.0 340.0 410.0 419.999969482 430.000030518 440.0 --------------------- 操作完后的结果 ---------------------
 ---->row-----           4
 ---->col-----           4
   91.10000               1           1           1
   51.20000               1           2           2
   1.350000               1           3           3
   1.450000               1           4           4
 ----row-----           1
   92.10000               2           1           5
   52.20000               2           2           6
   2.350000               2           3           7
   2.450000               2           4           8
 ----row-----           2
   93.10000               3           1           9
   53.20000               3           2          10
   3.350000               3           3          11
   3.450000               3           4          12
 ----row-----           3
   94.10000               4           1          13
   54.20000               4           2          14
   4.350000               4           3          15
   4.450000               4           4          16
 ----row-----           4
9110.0 5120.0 135.0 145.0 9210.0 5220.0 234.999984741 245.0 9310.0 5320.0 335.0 345.0 9410.0 5420.0 435.0 444.999969482 --------------------- 操作完后的结果 ---------------------
 ---->row-----           4
 ---->col-----           4
   110.0000               1           1           1
   120.0000               1           2           2
   130.0000               1           3           3
   140.0000               1           4           4
 ----row-----           1
   210.0000               2           1           5
   220.0000               2           2           6
   230.0000               2           3           7
   240.0000               2           4           8
 ----row-----           2
   310.0000               3           1           9
   320.0000               3           2          10
   330.0000               3           3          11
   340.0000               3           4          12
 ----row-----           3
   410.0000               4           1          13
   420.0000               4           2          14
   430.0000               4           3          15
   440.0000               4           4          16
 ----row-----           4
11000.0 12000.0009766 13000.0 14000.0 20999.9980469 22000.0 23000.0 24000.0019531 31000.0 32000.0 33000.0 34000.0 41000.0 41999.9960938 43000.0039062 44000.0 默认传给dll的是指针,因此在fortran中如果动了地址里面的内容,那么反映到python上也会跟着改变

Regarding fortran arrays:

Syntactically, assumed shape used colons (:) instead of 
an asterisk in the dimension declaration.  The difference in meaning 
is exactly the subject in question - assumed shape arrays automatically 
get their shape information passed, whereas assumed size arrays basically 
get nothing but a starting address passed. 

http://computer-programming-forum.com/49-fortran/f2a81d00123cad00.htm

 

Running python encounters this error error: Unable to find vcvarsall.bat It can be solved like this:

Reason for the error: When generating, the compiler cannot find the vcvarsall.bat file from the find_vcvarsall(version) function on line 219 in %PythonInstallPath%\distutils\msvc9compiler.py.

The more specific reason is that msvc9compiler.py extracts the version number of MSVC from sys.version, but does not find vcvarsall.bat according to the version number in the registry, nor does it find the path corresponding to the version number in the system environment variables. Later, I added the path to the environment variable according to the version number, but because msvc9compiler.py is mainly for path recognition for VS2008 and VS2010, it still cannot find vcvarsall.bat correctly.

Solution: Return the absolute path of vcvarsall.bat directly in the find_vcvarsall(version) function.

https://blog.csdn.net/sad_sugar/article/details/73743863

Tip: After running .bat, it is equivalent to adding the environment variables of various tools of vs. We can use dumpbin /symbols xxx.lib to see how many functions are available in the lib for us to use

 

I encountered such a problem during the installation of VS 2015 (even the version downloaded from the official website will encounter https://www.visualstudio.com/zh-hans/vs/older-downloads/ ):

setup detected an issue during the operation.

"The installer has detected a problem..."

The workaround is:

Find the C:\Windows\Fonts directory,
back up all the fonts under fonts
and delete all the fonts under C:\Windows\Fonts (if the system font cannot be deleted, keep it, some font sets prompt warning not to delete, also Keep it)
and then install vs2015 and it's OK!
This question is really weird, but that's how it was solved: https://stackoverflow.com/questions/33622151/setup-detected-an-issue-during-visual-studio-community-edition-2015-installation

 

When this error occurs Visual Studio cannot debug because a debug target has not been specified or cannot start debugging because the debug target is missing

(It is especially easy to appear when compiling dll, you can choose an exe to debug)

 

 

When editing fortran in VS, if we want to enable the jump to definition function, set it here:

Enable fortran jump to definition

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325508197&siteId=291194637