2017-01-26 1 views
2

Nach einigen Online-Graben und Trial-Fehler, frage ich mich immer noch, wie übergeben Arrays von Strings von Python zu Fortran von f2py.Wie man Zeichenketten an Fortran Subroutine mit f2py übergeben

Ich habe die Fortran-Unterprogramm in string.f90 als:

SUBROUTINE FOO(A) 
    CHARACTER*5,dimension(10),intent(inout):: A 
    PRINT*, "A=",A 
    END 

Dann laufe ich f2py -m mystring -c string.f90. Das Kompilieren war erfolgreich.

Die Python-Sitzung in test.py ist:

import mystring 
import numpy as np 
nobstot=10 
xstring=np.empty(nobstot,dtype='S5') 
xstring[0]="ABCDE" 
mystring.foo(xstring) 

Run python test.py, ich habe die Fehlermeldung:

1-th dimension must be 5 but got 0 (not defined). 
Traceback (most recent call last) : 
File "test.py", line 6, in <module> 
mystring.foo(xstring) 
mystring.error: failed in converting 1st argument `a' of mystring.foo to C/Fortran array 

Im f2py Kompilieren Schritt die gfortran und gcc-Compiler wurden aufgerufen.

Nach >>> print mystring.foo.__doc__ gab es:

foo(a) 
Wrapper for ``foo``. 
Parameters 
--------- 
a : in/output rank-2 array('S') with bounds (10,5) 

So habe ich versucht, test.py wie:

import mystring 
import numpy as np 
nobstot=10 
xstring=np.empty((nobstot,5),dtype='S1') 
print xstring.shape 
xstring[0]="ABCDE" 
mystring.foo(xstring) 

Dann python test.py laufen, wird die Fehlermeldung lautet:

Traceback (most recent call last): 
File "test.py", line 7, in <module> 
mystring.foo(xstring) 
ValueError: failed to initialize intent(inout) array -- input 'S' not compatible to 'c' 
+0

nicht Grüße Fügen Sie zu Ihrem Post. Ihr Name wird automatisch in der Nähe Ihres Symbols unter Ihre Frage gestellt. –

+0

@Vladimire F. Verstanden. Vielen dank für Deine Hilfe. –

Antwort

2

Erstens, um Array von Zeichenfolgen an Fortran zu übergeben, müssen Sie in Python ein Array von Zeichen mit der Form (<number of strings>, <string length>) erstellen, füllen Sie den Inhalt und übergeben Sie dann das Char-Array zu F2py generierte Funktion. Mit Ihrem Beispiel:

xstring = np.empty((nobstot, 5), dtype='c') 
xstring[0] = "ABCDE" 
xstring[1] = "FGHIJ" 
mystring.foo(xstring) 

Um dies zu arbeiten, müssen Sie auch Ihren Fortran-Code ändern:

subroutine foo(A) 
character*5, dimension(10), intent(in) :: A 
print*, "A(1)=",A(1) 
print*, "A(2)=",A(2) 
end 

Beachten Sie, dass intent(inout) mit intent(in) ersetzt wird. Dies liegt daran, dass Strings in Python genauso wie Strings in numpy Arrays von Strings unveränderlich sind, in Fortran jedoch nicht. Daher kann das Speicherlayout von Python-Zeichenfolgen nicht einfach an Fortran-Funktionen übergeben werden, und der Benutzer muss die Zeichenfolgendaten wie oben erläutert reorganisieren. Wenn Ihr Fortran-Code die Zeichenfolgen ändert, müssen Sie, wie die Verwendung von intent(inout) andeutet, solche Zeichenfolgenargumente wie beispielsweise intent(in, out) deklarieren, indem Sie beispielsweise die Anweisung f2py verwenden.Hier folgt ein vollständiges Beispiel:

subroutine foo(A) 
character*5, dimension(10), intent(inout) :: A 
!f2py intent(in, out) A 
print*, "A(1)=",A(1) 
print*, "A(2)=",A(2) 
A(1)="QWERT" 
end 

f2py Aufruf:

f2py -m mystring -c string.f90 

Python Testskript:

import mystring 
import numpy as np 
nobstot = 10 
xstring = np.empty((nobstot, 5), dtype='c') 
xstring[0] = "ABCDE" 
xstring[1] = "FGHIJ" 
xstring = mystring.foo(xstring) 
print("xstring[0]=",string[0].tostring()) 
print("xstring[1]=",string[1].tostring()) 

Console Ausgabe:

A(1)=ABCDE 
A(2)=FGHIJ 
xstring[0]= QWERT 
xstring[1]= FGHIJ 
+0

Ich verstehe nicht, warum der Fortran-Code so geändert werden sollte, wie Sie ihn zeigen. (Abgesehen von dem Syntaxfehler Tippfehler.) –

+0

Normalerweise wird '! F2py intent (in, out) A' nicht benötigt, da Fortran' intent (inout) 'stattdessen automatisch verwendet wird. Was ist der Grund, warum Sie sagen, dass es hier gebraucht wird? –

+0

Der wahre Grund, warum '! F2py intent (in, out)' benötigt wird, ist, dass die f2py-Unterstützung für String-Arrays unvollständig ist. Nach der aktiven Entwicklung von f2py wurden numpy String-Arrays eingeführt. Wenn Sie die String-Array-Unterstützung vervollständigen, würde die Verwendung von numpy String-Arrays dieses Problem endgültig beheben. Bis dahin kann man immer noch f2py benutzen, aber mit den oben genannten Einschränkungen (benutze numpy Char-Arrays anstelle von numpy String-Arrays). – Pearu

0

Kommunizieren Zeichenfolge und von Fortran ist ein wenig schwierig.

Mit dieser Linie establisted Sie praktisch zwei-dimensionalen Charakter-Array 10 * 5

CHARACTER*5,dimension(10),intent(inout):: A 

versuchen es

CHARACTER*10,intent(inout):: A 

ändern, dass sie eine eindimensionale Anordnung von 10 Zeichen macht. Wenn es funktioniert, aber die Ausgabe ist Müll, überprüfen Sie, ob beide das gleiche Zeichenformat (Ascii/Multibyte oder Unicode) sind.

+0

Vielen Dank. Ja, wenn es als Skalar von String deklariert ist, ist das Python-Skript in Ordnung. Und glücklicherweise scheint die Ausgabe wie erwartet in Ordnung zu sein. Um jetzt zu sein, bleibe ich bei deinem Vorschlag für meine Absicht. Wenn ich irgendwelche neuen Informationen oder eine einfachere Lösung habe, die einfacher in realen Fällen verwendet werden können, werde ich sie hier aktualisieren. Um jetzt zu sein, werde ich einige Zeit warten, um zu sehen, ob es noch andere Vorschläge gibt, bevor ich deine als Antwort auswähle. –

+0

Ein Update: Ich fand in der Fortran-Subroutine, könnte es als das Zeichen der einstellbaren Länge, wie zum Beispiel: CHARACTER (*), Absicht (inout) :: A erklärt werden. Dies wird dieses Schema mächtiger als ich dachte. –

+0

10 mal 5 = 50, warum also CHARACTER * 10 und nicht CHARACTER * 50? –

Verwandte Themen