vorbei char-arrays aus c++ -, fortran
Ich habe Schwierigkeiten beim char-arrays aus c++ -, fortran (Fortran 90).
Hier ist meine c++ Datei', ' cmain.cxx":
#include <iostream>
using namespace std;
extern "C" int ftest_( char (*string)[4] );
int main() {
char string[2][4];
strcpy(string[0],"abc");
strcpy(string[1],"xyz");
cout << "c++: string[0] = '" << string[0] << "'" << endl;
cout << "c++: string[1] = '" << string[1] << "'" << endl;
ftest_(string);
return 0;
}
Hier ist mein fortran-Datei, 'ftest.f90':
SUBROUTINE FTEST(string)
CHARACTER*3 string(2)
CHARACTER*3 expected(2)
data expected(1)/'abc'/
data expected(2)/'xyz'/
DO i=1,2
WRITE(6,10) i,string(i)
10 FORMAT("fortran: string(",i1,") = '", a, "'" )
IF(string(i).eq.expected(i)) THEN
WRITE(6,20) string(i),expected(i)
20 FORMAT("'",a,"' equals '",a,"'")
ELSE
WRITE(6,30) string(i),expected(i)
30 FORMAT("'",a,"' does not equal '",a,"'")
END IF
ENDDO
RETURN
END
Den build-Prozess ist:
gfortran -c -m64 ftest.f90
g++ -c cmain.cxx
gfortran -m64 -lstdc++ -gnofor_main -o test ftest.o cmain.o
Edit: beachten Sie, dass die ausführbare Datei kann auch erstellt werden über:
g++ -lgfortran -o test ftest.o cmain.o
Auch, die -m64-flag ist erforderlich, da ich unter OSX 10.6.
Die Ausgabe aus der Ausführung von "test":
c++: string[0] = 'abc'
c++: string[1] = 'xyz'
fortran: string(1) = 'abc'
'abc' equals 'abc'
fortran: string(2) = 'xy'
'xy' does not equal 'xyz'
Deklaration der 'string' und 'erwartet', Zeichen-arrays in ftest.f90 mit Größe 4, ie:
CHARACTER*4 string(2)
CHARACTER*4 expected(2)
und dann gibt die folgende Ausgabe:
c++: string[0] = 'abc'
c++: string[1] = 'xyz'
fortran: string(1) = 'abc'
'abc' does not equal 'abc '
fortran: string(2) = 'xyz'
'xyz' does not equal 'xyz '
Erklärung der Zeichen-arrays in 'cmain.cxx' mit Größe 3, dh:
extern "C" int ftest_( char (*string)[3] );
int main() {
char string[2][3];
sowie das zurücksetzen auf die original-Größe in der fortran-Datei (3), ie:
CHARACTER*3 string(2)
CHARACTER*3 expected(2)
und dann gibt die folgende Ausgabe:
c++: string[0] = 'abcxyz'
c++: string[1] = 'xyz'
fortran: string(1) = 'abc'
'abc' equals 'abc'
fortran: string(2) = 'xyz'
'xyz' equals 'xyz'
Also der Letzte Fall ist der einzige, der funktioniert, aber hier habe ich zugewiesen 3 Zeichen ein char-array der Größe 3, was bedeutet das abschließende '\0' fehlt, und führt zu der 'abcxyz' output - dies ist nicht akzeptabel für meine beabsichtigte Anwendung.
Jegliche Hilfe würde sehr geschätzt werden, dies treibt mich Nüsse!
- Ich sehe keine Anzeichen, dass Sie mit Fortran ist "Interoperabilität mit C' - Funktionen, die entworfen sind, um die Leichtigkeit solchen Problemen wie Sie konfrontiert sind. Ich schlage vor, Sie tun Sie verwenden.
- Hallo Markus, ich habe eine extern zur Verfügung gestellte fortran-Programm, dass ich mir Wünsche Schnittstelle über c++. Ich kann nicht ändern Sie die fortran-code. Sehen Sie einen Weg, um diesem zu arbeiten, ohne änderung der ursprünglichen fortran-Datei?
- Es hängt von der tatsächlichen Art der Anbindung Sie tun, aber wenn Sie die Fortran-code, auch wenn Sie es nicht ändern, man könnte hinzufügen, ein C-interface Modul. Das Modul würde einfach einige Funktionen für die Konvertierung sichtbar C. Als bonus, die Sie bekommen konnte loszuwerden, die nachgestellte _ in der Funktion Namen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
C-strings sind null-terminiert in der Erwägung, dass fortran-strings, per Konvention ist der Raum gepolstert, aber fester Größe. Sie sollten nicht erwarten, dass passieren können C-strings zu fortran ohne irgendeine Konvertierung.
Beispiel:
Den Sie dann verwenden können, die entweder mit der 3-oder 4-Länge-version von
ftest
:Ich empfehlen die Verwendung der ISO-C-Bindung auf Fortran-Seite wie vorgeschlagen durch "High-Performance-Marke". Sie sind bereits mit "extern C". Der ISO-C-Bindung von Fortran 2003 (derzeit in den meisten Fortran-95 /partielle Fortan 2003-Compiler) macht dies zu einem compiler-und Plattform-unabhängigen Ansatz. Charles Bailey beschrieb die Unterschiede zwischen strings in den beiden Sprachen. Diese Stackoverflow-Frage ein code-Beispiel: Aufruf eines FORTRAN-Unterprogramms aus C
Wenn Sie nicht wollen, zu ändern bestehenden Fortran-code, den Sie schreiben, könnte eine "Kleber" - routine, in der zwischen dem C++ - code und die vorhandenen Fortran-code. Schreiben Sie den Kleber routine in Fortran unter Verwendung des ISO-C-Bindung wäre zuverlässiger und stabiler, da diese basiert auf den Funktionen der Sprache standard.
Sind die Beispiele viel zu schwerwiegend, solange Sie nicht verzichten möchten, mehr als ein string ist, können Sie Gebrauch machen von "versteckten" parameter "length" ...
die Sie aufrufen können, fortran wie
Brauchen Sie nicht zu faff, über die mit den einzelnen Kopiervorgängen, da die std::string Konstruktor kann all das für Sie.
bind(C)
ist einfach), aber Sie sind tragbar. Es gibt nichts in der Fortran-standard, der sagt, dass die Funktion symbol wird der name mit Unterstrich und es gibt nichts, was garantiert, die den Typ des hidden-argument und seine position in der Argumentliste. Es gibt auch keine Garantie, es gibt keine versteckten argument.