C++ Math Library v2 und API (Application Programm Interface)

MATLAB C/C++ Math Library v2 und API (Application Programm Interface) Kurze Beschreibung und Anleitung zur Anwendung der Bibliotheken in eigenen C/C+...
Author: Axel Kopp
8 downloads 0 Views 617KB Size
MATLAB C/C++ Math Library v2 und API (Application Programm Interface)

Kurze Beschreibung und Anleitung zur Anwendung der Bibliotheken in eigenen C/C++ Programmen (Mit stärkeren Bezug auf den Microsoft Visual C++ 5.0 Compiler)

Nektarios Panagias IAF Automatisierungssysteme FH-Ulm Juli 2000

MATLAB C/C++ Bibliotheken und API Die MATLAB-Bibliotheken kann man in die API (Application Programm Interface) und die C/C++ Bibliotheken einteilen. In der API sind folgende Bibliotheken enthalten: • MX-Bibliothek: Dort sind alle Routinen für den Umgang mit den MATLAB-Arrays enthalten, wie Erzeugung, Zugriff und Löschen. Diese Bibliothek wird auch von den C/C++ Bibliotheken verwendet. Die Funktionsnamen dieser Bibliothek beginnen mit mx. • MAT-Bibliothek: Hier sind alle Routinen für den Umgang mit den MAT-Dateien (das MATLAB-Datenformat zur platzsparenden Speicherung von Daten) enthalten. Die C/C++ Bibliotheken verwenden diese Bibliothek beim Laden oder Speichern von Daten. Die Funktionsnamen dieser Bibliothek beginnen mit mat. • Engine-Bibliothek: Dadurch kann der MATLAB-Interpreter von einem eigenen Programm aus ferngesteuert werden (über ActiveX). MATLAB läuft dabei im Hintergrund und kann wie gewohnt bedient werden, nur von einem C-Programm aus. Die Funktionsnamen dieser Bibliothek beginnen mit eng. • MEX-Bibliothek: Damit können eigene C-Programme in mex-Dateien kompiliert werden, die der MATLAB-Interpreter wie die built-in Funktionen ausführen kann. Dadurch können z.B. Berechnungen, die mit einem M-File zu langsam laufen würden (z.B. viele große for-Schleifen) stark beschleunigt werden. Die Funktionsnamen dieser Bibliothek beginnen mit mex. Diese Bibliothek wird hier nicht behandelt. • Weiterhin bietet die API Client-Server Anwendungen mit ActiveX und DDE, die hier nicht besprochen werden. Die MATLAB C Bibliothek ist in zwei Bibliotheken aufgeteilt: • Die built-in Bibliothek enthält alle built-in Funktionen von MATLAB. Das sind Funktionen für die MATLAB-Operatoren, elementare Matrix Manipulation und elementare mathematische Funktionen, die jedes Programm benötigt und somit essentiell sind. • Die M-File – Bibliothek enthält alle Funktionen, die dem Interpreter normalerweise als M-Files zur Verfügung stehen (daher der Name) und für spezielle Anwendungen verwendet werden, z.B. hilb, pascal, interpol1. Alle Funktionsnamen beginnen mit mlf. Die M-File Bibliothek ist viel größer als die built-in Bibliothek. Aus Gründen des Platz Sparens wurden die Matlab-Funktionen in zwei Bibliotheken getrennt. Programme die keine speziellen Funktionen benötigen, brauchen nur die kleinere built-in Bibliothek einzubinden. Die MATLAB C++ Bibliothek ist objektorientiert aufgebaut und erlaubt eine viel einfachere Handhabung der MATLAB-Funktionen. Die C++ Bibliothek bietet nur eine vereinfachte objektorientierte Schnittstelle, greift aber im Grunde intern auf die C-Bibliotheken zurück (weshalb diese auch benötigt werden). Die Funktionsnamen haben hier keinen Präfix und lauten genauso wie die MATLAB-Funktionen. Allerdings hat sich die Einbindung der C++ Bibliothek in ein eigenes Programm als schwieriger erwiesen als die einfache C Bibliothek. Wichtige Hinweise: • Alle Toolboxen, Simulink und Graphikausgaben sind nicht in den Bibliotheken enthalten! Graphikausgaben können (und sollten) vom eigenen C-Programm ausgeführt werden. Für die Toolboxen kann ein komplizierter Weg versucht werden, der auf S.9 beschrieben wird. Als Alternative kann die Engine verwendet werden. Allerdings muß bei der Engine auf dem Rechner MATLAB laufen.

2



Die Bibliotheken wurden nur mit dem Microsoft Visual C++ 5.0 Compiler (MSVC) eingesetzt und verwendet. Es werden nur Tips für den MSVC gegeben. Für andere Compiler (z.B. Borland) kann nur das angegeben werden, was der Anleitung zu entnehmen ist.

Dokumentation: In der MATLAB-HTML-Hilfe (helpdesk) sind alle Funktionen der Bibliotheken enthalten, mit der gleichen Gliederung wie sie oben vorgestellt wurden. Die MX-, MAT- und EngineFunktionen unter „Application Program Interface“, die C-Funktionen unter „MATLAB C Math Library 2.0 Ref.“ und die C++ Funktionen unter „MATLAB C++ Math Library 2.0 Ref.“. Eine genauere Beschreibung der Bibliotheken mit Beispielen ist in den Handbüchern zu finden, die auch in pdf-Form vorliegen (falls installiert) unter dem Pfad: \help\pdf_doc\ Beispiel: Auf dem Rechner IAF-PANAJAS im Verzeichnis WELCOME\MATLAB_DEMO ist ein Beispiel-Programm ‚MatlabDemo‘ mit Source Code und allen benötigten Dateien enthalten. Das Zip-File enthält alle Dateien damit es auf einen Rechner der MATLAB schon installiert hat läuft. Demnächst kann es auf meiner homepage downgeloaded werden (Erreichbar über die IAF-WebSeite). Das Beispiel-Programm berechnet auf fünf verschiedenen Weisen den Ausgang eines Neuronalen Netzes, das in der Datei netz.mat gespeichert ist. Das Netz hat sechs Eingänge und zwei Ausgänge (es ist ein Neuronales Netz, das mit dem Rollkugelspiel trainiert wurde). Bei allen fünf Berechnungsarten wird zuerst das Netz aus der Datei geladen, berechnet und die Ausgangswerte (x und y) angezeigt. Folgende fünf Möglichkeiten werden demonstriert: • • • • •

C Library: Die Berechnung erfolgt mit Funktionen aus der MATLAB C Bibliothek. C++ Library: Die Berechnung erfolgt mit Funktionen aus der MATLAB C++ Bibliothek. M-file -> C Funktion: Eine M-file-Funktion, die diese Berechnung macht, wurde mit dem MATLAB Compiler in einen C Code übersetzt und vom Demo-Programm aufgerufen. M-file -> C++ Funktion: Eine M-file-Funktion, die diese Berechnung macht, wurde mit dem MATLAB Compiler in einen C++ Code übersetzt und vom Demo-Programm aufgerufen. Matlab Engine: Eine MATLAB-Engine wird gestartet und ein M-file, welches dort das Netz lädt, berechnet und die Ausgänge ausgibt, ausgeführt. Der MATLAB-Ausgabetext wird gelesen und im Demo-Programm angezeigt.

Damit die Engine-Demo überhaupt funktioniert muß auf dem Rechner, der das Demo-Programm ausführt, MATLAB installiert sein. Durch den Schalter neben dem Engine-Button kann entschieden werden ob die Engine nach der Berechnung geschlossen werden soll, oder noch offen bleibt (bei der nächsten Berechnung muß MATLAB nicht wieder neu geladen werden und die Engine kann sofort ohne Verzögerung verwendet werden). Die notwendigen dll’s sind auch auf diesem Verzeichnis, falls MATLAB nicht installiert ist. Allerdings kann damit die Engine trotzdem nicht getestet werden, da MATLAB unbedingt notwendig ist. Der Rest sollte trotzdem funktionieren. Auf eine ausführliche Beschreibung des Demo-Programms wurde verzichtet, da alles notwendige im Vortrag erläutert wird. Der Quellcode ist dokumentiert. 3

MATLAB - Bibliotheken und dlls Im \matlab\bin – Verzeichnis sind alle Dynamic Link Libraries (*.dll) enthalten, welche die eigenen Anwendungen benötigen. Dieses Verzeichnis sollte deshalb im Suchpfad (PATH) enthalten sein oder die entsprechenden dll´s zusammen mit der Anwendung kopiert werden, falls z.B. die Anwendung auf einem Rechner ohne MATLAB verwendet wird. Folgende Tabelle zeigt die wichtigsten dll´s. Welche davon im Endeffekt benötigt werden, hängt von der Anwendung ab. (Im schlimmsten Fall einfach ausprobieren.) dll`s Pfad: \bin\ libmatlb.dll Die MATLAB built-in Math Library. Enhält alle Built-in Funktionen und Operatoren von Matlab und wird somit immer benötigt libmmfile.dll Die MATLAB M-File Math Library. Enthält die mathematischen M-File Funktionen in eigenständiger Form. libmat.dll Routinen die den Zugriff auf MAT-Files steuern. libmx.dll MATLAB API Library. Enthält Routinen für Array Zugriff libeng.dll Enthält die Routinen für die Matlab Engine libmi.dll Interne mathematische Routinen (weitere Informationen darüber fehlen). libut.dll MATLAB Utilities Library. Enthält Utility-Routinen die verschiedene Komponenten benötigen. libmcc.dll MATLAB Compiler Library für eigenständige Anwendungen. Enthält die mcc und mcm Routinen zum erstellen eigenständiger Anwendungen. In das eigene C/C++ Programm müssen Bibliotheksdateien (*.lib) eingebunden werden (die nicht in dieser Form vorhanden sind). Im Verzeichnis \extern\include sind sogenannte Defininionsdateien (*.def) enthalten, aus denen die Bibliotheksdateien erzeugt werden können (auf der nächsten Seite Infos dazu). Es sind def-Dateien für den MSVC und dem Borland Compiler enthalten, die sich folgendermaßen unterscheiden lassen: Borland: _lib*.def MSVC: lib*.def. Definitionsdateien (*.def) Pfad: \extern\include\ libmatlb.def Enthält die Funktionsnamen die von libmatlb.dll exportiert werden. _libmatlb.def libmmfile.def Enthält die Funktionsnamen die von libmmfile.dll exportiert werden. _libmmfile.def libmat.def Enthält die Funktionsnamen die von libmat.dll exportiert werden. _libmat.def libmx.def Enthält die Funktionsnamen die von libmx.dll exportiert werden. _libmx.def libeng.def Enthält die Funktionsnamen die von libeng.dll exportiert werden. _libeng.def libut.def Enthält die Funktionsnamen die von libut.dll exportiert werden. _libut.def libmcc.def Enthält die Funktionsnamen die von libmcc.dll exportiert werden. _libmcc.def

4

Umgang mit den *.def -Dateien: Borland:

Die entsprechenden _lib*.def – Dateien können laut Anleitung direkt eingebunden werden. MSVC: Die lib*.def – Dateien müssen erst in Bibliotheken (*.lib) umgewandelt werden. Am Besten mit dem folgenden Befehl in der Linker Vorstufe ( Unter dem Menü(s): Projekt Einstellungen Linker-Vorstufe Befehl(e) der Linker-Vorstufe): lib def:“\extern\include\libmatlb.def“ ( steht für den MATLAB-Pfad. Einsetzen!). Die entsprechende *.lib-Datei wird in das aktuelle Verzeichnis des Compilers geschrieben. Diese muß dann in das Projekt eingebunden werden. Für die C++ Bibliothek gibt es weitere Bibliotheksdateien, wobei für jeden Compiler eine eigene *.lib Datei existiert. Das Verzeichnis ist \extern\lib. Folgende Tabelle zeigt die Compiler-spezifischen *.lib Dateien. C++ Bibliothek Pfad: \extern\lib Libmatpb50.lib MATLAB C++ Bibliothek für die Borland Libmatpb52.lib C++ Compiler v5.0, v5.2 und v5.3 Libmatpb53.lib MATLAB C++ Bibliothek für den Microsoft Libmatpm.lib Visual C++ Compiler Libmatpw106.lib MATLAB C++ Bibliothek für den Watkom Libmatpw11.lib C++ Compiler v10.6 und v11. Einbinden der *.lib Bibliotheken Das Einbinden der Bibliotheken ist für jeden Compiler unterschiedlich. Für den MSVC Compiler geht dies übers folgende Menü(s): Projekt Dem Projekt hinzufügen Dateien

Falls eine *.lib Datei nicht eingebunden wurde, aber vom Linker benötigt wird, kann folgende Fehlermeldung auftreten (so ähnlich): Nichtaufgelöstes externes Symbol ... Dies ist meist ein Zeichen, dass eine *.lib Datei fehlt. Das Präfix dieses fehlenden Symbols kann meist Auskunft geben über die fehlende Datei ( ist das Präfix z.B. ‚mx‘, so fehlt die libmx.lib Datei).

5

Verwendung der MATLAB – Engine Bibliothek • • • • • • •

Include-Verzeichnis hinzufügen: \extern\include Header einbinden: #include Bibliotheksdatei einbinden: libeng.lib Falls sie noch nicht existiert, aus der Definitionsdatei erzeugen (siehe S.3&4). Falls Funktionen der anderen Bibliotheken verwendet werden (z.B. C, C++) entsprechende Headerfiles und Bibliotheksdateien auch einbinden (siehe dort). Im Programm einen Engine-Zeiger deklarieren: Engine *eng; Im Programm die MATLAB Engine starten: eng = engOpen("\0"); Am Besten mit einer Abfrage ob Versuch geglückt ist (siehe Beispiel). Engine verwenden, mit folgenden möglichen Befehlen: Engine* engOpen(const char *startcmd); Startet die MATLAB-Engine (siehe oben). Bei Windows ist nur NULL ("\0") als startcmd zu verwenden. Es wird der Zeiger auf diese Engine zurückgegeben. int engEvalString(Engine *ep, const char *string); Sendet an die gestartete MATLAB-Engine ep den Ausdruck string, der von MATLAB ausgeführt werden soll. Ausgaben auf dem Command Window werden unterdrückt. Falls die Engine nicht mehr existiert wird eine Zahl ungleich 0 zurückgegeben. int engOutputBuffer(Engine *ep, char *p, int n); Definiert einen Textpuffer p der Länge n für engEvalString der alle Ausgaben, die normalerweise auf den Bildschirm (Command window) erscheinen würden, empfängt. int engPutArray(Engine *ep, mxArray *mp); Stellt ein mxArray mp in die workspace der MATLAB-Engine ep. Falls diese in der workspace noch nicht existiert, wird diese dort erzeugt. Falls eine Variable mit diesem Namen schon existiert, wird diese überschrieben. mxArray *engGetArray(Engine *ep, const char *name); Holt ein mxArray aus der workspace der MATLAB-Engine ep mit der Bezeichnung name. int engClose(Engine *ep); Schließt die MATLAB-Engine ep und gibt 0 zurück falls erfolgreich. Ein Fehler kann vorkommen, falls versucht wird eine schon geschlossene Engine zu schließen.

Hilfe: Die Beschreibung der Engine-Bibliothek ist dem API - Handbuch „Application Program Interface“ (pdf-Form: \help\pdf_doc\matlab\api\apiguide.pdf) zu entnehmen in dem auch die MX- und die MAT-Bibliothek beschrieben wird, ebenso wie die Verwendung von ActiveX und DDE. Die HTML-Hilfe ist unter „Application Program Interface“ zu finden. 6

Verwendung der MATLAB C Bibliothek (mit dem MSVC Compiler) • • •

Include-Verzeichnis hinzufügen: \extern\include Header einbinden: #include Bibliotheken einbinden: libmx.lib und libmatlb.lib (Zuerst erzeugen, siehe S. 3&4) (u.U. noch libmmfile.lib oder sogar weitere, je nach Anwendung. Siehe S.3&4)

Die C Bibliothek arbeitet mit der mxArray Variable, die den MATLAB-Arrays entspricht. Dazu einige Informationen: • mxArrays sind (wie die MATALB-Arrays) zeilenweise orientiert, jedoch die C-Arrays spaltenweise (erster Index bei mxArray entspricht der Zeile und der zweite der Spalte. Bei den C-Arrays ist es genau umgekehrt). Also Vorsicht bei der Umwandlung in die beiden Formen (z.B. beim Zuweisen eines mxArrays mit einem C-Array). • Ein deklariertes mxArray (Zeiger) muß nach der Verwendung mit mxDestroyArray() gelöscht werden, damit der reservierte Speicher freigegeben wird. Die Speicherfreigabe geschieht nicht automatisch beim Funktionsende (wie z.B. bei double) und muß manuell erfolgen, ansonsten wird Speicher „gefressen“. • Normalerweise können einer Funktion keine weiteren Funktionen als Parameter übergeben werden (wie z.B. y=sin(tan(x)) ), sondern es müssen temporäre Variablen verwendet werden (die am Ende natürlich auch manuell gelöscht werden müssen). Es ist aber auch ein automatisches Speichermanagement möglich, mit dem beliebig Funktionen als Funktionsparameter übergeben werden können ohne dass Speicher verloren geht. Das automatische Speichermanagement wird am Anfang der C-Funktion mit mlfEnterNewContext(0,0); und am Funktionsende mit mlfRestorePreviousContext(0,0); beendet. Die Zuweisungen sollten dabei mit mlfAssign() erfolgen (z.B. anstatt y=sin(tan(x)) Õ mlfAssign(&y,sin(tan(x))) ). Bei der Verwendung der C Bibliothek sollte das automatische Speichermanegement verwendet werden. Informationen dazu im Kapitel 4 „Managing Array Memory“ im „MATLAB C Math Library, User’s Guide“. Hilfe: Die Beschreibung der C Bibliothek ist dem „MATLAB C Math Library, User’s Guide v2“ (pdf-Form: \help\pdf_doc\mathlib\cmath_ug2b.pdf) zu entnehmen, in dem auch einige Beispiele enthalten sind. Die Befehle sind im „MATLAB C Math Library, Reference v2“ aufgeführt, und auch in der HTML-Hilfe.

7

Verwendung der MATLAB C++ Bibliothek (mit dem MSVC Compiler) • • •

Include-Verzeichnis hinzufügen: \extern\include Header einbinden: #include Bibliotheken einbinden: \extern\lib\libmatpm.lib* Zusätzlich: libmx.lib und libmatlb.lib (Zuerst erzeugen. Siehe S.3&4) (u.U. noch libmmfile.lib oder sogar weitere, je nach Anwendung. Siehe S.3&4)

Mit dem Microsoft Visual C++ 5.0 Compiler traten einige Probleme auf. Durch folgende zusätzliche Eingriffe lassen sie sich beheben: • Den Header matlab.hpp nach den vom Klassen-Assistent eingefügten includes und vor den (auch vom Klassen-Assistent eingefügten) #ifdef _DEBUG .... einbinden. • Vor dem #include folgende Variablen definieren: #define MSVC (oder BORLAND) #define MSWIND (Vielleicht gibt es einen anderen Weg um dies zu umgehen. Den kenne ich aber nicht.) • Zusätzlich musste die (Header-)Datei \extern\include\cpp\mltif.h leicht verändert werden. In der Zeile 5231 ist der Funktionskopf für die Matlab-Funktion pascal deklariert. Der Compiler hat jedoch ein gleichnamiges Schlüsselwort und interpretiert dies falsch. Ich habe an der genannten Stelle aus pascal Õ Pascal gemacht und die Datei gespeichert. Es gab keine Fehler mehr und sogar die MATLAB - Pascal–Funktion mit der neuen Schreibweise (das P groß) funktionierte bei einem Test einwandfrei. Die C++ Library arbeitet mit der mwArray Variable (Klasse). Intern werden jedoch mxArrays verwendet (siehe S.7). Bei den mwArrays muss nicht auf die Speicherverwaltung geachtet werden, da alles automatisch durch die Konstruktoren und Destruktoren erledigt wird. Einfach wie bei normalen Variablen (z.B. double) vorgehen. Es können auch ohne Bedenken Funktionen als Funktionsparameter angegeben werden. Allein zu Umwandlungen sollen hier einige Worte gesagt werden: • double mwArray: Bei der Deklaration eines mwArrays (x,y: Reihen, Spalten) mwArray ma(x,y,c_array); • mxArray mwArray: Auch durch Konstruktor • mwArray mxArray: Durch die Memberfuntion GetData() mxArray mxa = ma.GetData(); • mwArray double: Einfache Zuweisung double d = ma(x,y); Hilfe: Die Beschreibung der C++ Bibliothek ist dem „MATLAB C++ Math Library, User’s Guide v2“ (pdf-Form: \help\pdf_doc\cppmath\cppmath_ug2b.pdf) zu entnehmen, in dem auch einige Beispiele enthalten sind. Die Befehle sind im „MATLAB C++ Math Library, Reference v2“ aufgeführt, und auch in der HTML-Hilfe. *

Bzw. die entspr. Bibliothek für den verwendeten Compiler (siehe S. 4)

8

M-File Þ C/C++ Code Übersetzen von (eigenen) M-Files in C/C++ Code mit mcc (MATLAB Compiler 2.0) Einbindung des übersetzten Codes in ein C/C++ Programm Der MATLAB-Compiler bietet sehr viele Möglichkeiten und es sollte die Anleitung dazu gelesen werden. Hier ist nur die Übersetzung eines M-Files in C/C++ Code stichwortartig dargestellt. Einschränkungen: • Keine Graphikbefehle (plot, usw.) können verwendet werden! • Keine Simulink Funtionen möglich! • Keine Toolbox-Funktionen möglich!



Die Einbindung von Toolboxen könnte möglich sein, wird sich jedoch als sehr schwierig erweisen. Dazu müsste das M-File der zu verwendeten Toolbox-Funktion übersetzt werden incl. aller weiteren ToolboxFunktionen die dort aufgerufen werden (usw., meist über mehrere Ebenen). Jede (Unter)Funktion muss dabei einzeln übersetzt werden. Alle Graphikausgaben müssen dabei unterdrückt oder zur Ausgabe durch das eigene C-Programm umgeleitet werden.

Eine Funtion, die in C/C++ übersetzt wird kann (im Gegensatz zu MATLAB-Funktionen) nur einen Rückgabewert haben. Falls mehrere erforderlich sind können diese als Funktionsparameter der Funktion übergeben werden. Nach diesem Prinzip sind übrigens alle C/C++ Funktionen der MATLAB-Bibliotheken aufgebaut. (Siehe in der Dokumentation unter ‚Calling Conventions‘.)

Übersetzung M-File C/C++ Code: mcc –t –L [c|cpp] xxx.m xxx.m -t -L [c|cpp] Ausgabe von mcc: Bei C: Bei C++:

ist das zu übersetzende M-file Durch diesen Schalter wird das M-file in C-Code übersetzt Sprache einstellen: Entweder C (default) oder C++.

xxx.c und xxx.h xxx.cpp und xxx.hpp

Einbinden ins C-Programm: Bei C: #include "xxx.c" (Nicht die Header-Datei!) Bei C++: #include "xxx.cpp" (Nicht die Header-Datei!) Und die zusätzlichen Veränderungen die auf S.8 erwähnt wurden. Funktionsaufruf im C-Programm: Bei C: Dem M-Funktion-Namen wird (beim Übersetzen) mlf vorgefügt und der erste Buchstabe des M-Funktion-Namens groß geschrieben. Heißt z.B. die M-Funktion: rechne.m , so wird die entsprechende C-Funktion durch mlfRechne() aufgerufen. Bei C++: Der Funktionsname ändert sich nicht. Heißt z.B. die M-Funktion rechne.m so heißt die C++ Funktion rechne(). Hilfe: In der HTML-Hilfe (...\\help\helpdesk.html) unter ‚MATLAB Compiler 2.0 Ref.‘ und die Bücher dazu im pdf-Format im Verzeichnis ...\\help\pdf_doc\compiler. 9