RegisterFunction

RegisterFunction trägt eine Funktion aus einer Dynamischen Link Library (DLL) in die UniScript-Symboltabelle ein. Danach ist ein direkter Aufruf der Funktion möglich.

nValue = RegisterFunction(ssDLL, ssExternalName, ssReturnType, ssInternalName, svParamTypes)

Returnwert

nValue ist eine Zahl größer 0, wenn die Funktion erfolgreich ausgeführt werden konnte. Falls ein Fehler auftrat, ist nValue kleiner oder gleich null.

Wert Bedeutung
0 ssInternalName kann nicht in die Symboltabelle eingetragen werden.
-1 Die DLL ssDLL wurde nicht gefunden oder konnte nicht geladen werden.
-2 Die Funktion ssExternalName wurde in der angegebenen DLL nicht gefunden.
-3 Der Parameter ssReturnType ist fehlerhaft.
-4 Der Parameter ssInternalName ist fehlerhaft.
-5 Der Parameter svParamTypes ist fehlerhaft.

Parameter

ssDLL

ssDLL ist der Name der DLL. Falls keine Dateinamenerweiterung angegeben wird, nimmt RegisterFunction die Endung .DLL an. Falls kein Pfad für die DLL angegeben wird, sucht RegisterFunction die DLL in den folgenden Verzeichnissen in der angegebenen Reihenfolge. Die Suchreihenfolge wird auch für DLLs verwendet, die für die angegebenen DLL geladen werden müssen:

  • Im UniPlot-Verzeichnis

  • Im aktuellen Verzeichnis

  • Im Windows System-Verzeichnis

  • Im Windows Verzeichnis

  • In den Verzeichnissen die in der PATH Environment-Variablen angegeben sind.

    Beispiel, wie der Pfad erweitert werden kann:

    ssPath = getenv("path");
    putenv("path=" + ssPath + ";" + ssDir);
    

Falls die DLL mit Pfad angegeben wird, müssen sich alle DLLs, die von der angegebenen DLL geladen werden, in einem der oben genannten Verzeichnisse befinden. Ansonsten wird als Fehlernummer -1 zurückgegeben.

ssExternalName

ssExternalName ist der exportierte Name der Funktion in der DLL. Falls der Funktionsname in der DLL nicht gefunden wurde, gibt RegisterFunction den Wert -2 zurück. Bei dem Namen ssExternalName werden Groß- und Keinbuchstaben unterschieden. Anstatt des Namens kann auch die Ordinalnummer der Funktion als String angegeben werden. Vor die Ordinalnummer muss dann ein Nummernzeichen geschrieben werden, z. B. #123.

ssReturnType

ssReturnType gibt den Returnwert der Funktion ssExternal an. Die möglichen Typen sind in der Tabelle unten angegeben. Falls die Funktion keinen Wert zurückgibt, muss "void" angegeben werden. Da UniScript immer einen Wert zurück gibt, gibt UniScript bei Aufruf einer solchen Funktion den Wert 1 zurück. Falls die Funktion aus der DLL einen Zeiger auf eine Struktur zurückgibt, kann ein "void*" angegeben werden.

ssInternalName

ssInternalName ist der Name unter dem die Funktion in UniScript aufgerufen werden soll. Es muss sich um einen gültigen Funktions-Namen handeln, d.h. der Name muss mit einem Unterstrich oder einem Buchstaben beginnen, dem beliebig viele Unterstriche, Buchstaben oder Ziffern folgen. Bei den Buchstaben sind keine länderspezifischen Buchstaben erlaubt (z. B. ä, ß).

svParamTypes

svParamTypes ist ein Vektor von Strings (maximal 32 Elemente), der die Parameter der Funktion ssExternalName beschreibt. In der linken Spalte der folgenden Tabelle sind die möglichen Daten-Typen der Parameter in der DLL angegeben. In der rechten Spalte steht der entsprechende UniScript-Datentyp. Da UniScript die meisten der C-Datentypen nicht besitzt, wird beim Aufruf eine Konvertierung durchgeführt.

Wert Bedeutung
„void“ „void“ wird für den Parameter ssReturnType verwendet, wenn die Funktion in der DLL keinen Returnwert zurückgibt. Da in UniScript Funktionen immer Werte zurückgeben, gibt UniScript in diesem Fall immer den Wert 1 zurück. Im Parameter svParamTypes darf „void“ nur angegeben werden, wenn die Funktion keine Parameter besitzt.
„char“ (1 Byte) Reeller Skalar oder skalarer String mit einem Zeichen.
„wchar_t“ (2 Bytes) Reeller Skalar oder skalarer String mit einem Unicode-Zeichen.
„uchar“ (1 Byte) Reeller Skalar oder skalarer String mit einem Zeichen.
„short“ (2 Bytes) Reeller Skalar.
„ushort“ (2 Bytes) Reeller Skalar.
„int“ (4 Bytes) Reeller Skalar.
„uint“ (4 Bytes) Reeller Skalar.
„int64“ (8 Bytes) Reeller Skalar.
„uint64“ (8 Bytes) Reeller Skalar.
„size_t“ (4 Bytes oder 8 Bytes, je nach UniPlot-Version. In der 64-Bit Version von UniPlot ist size_t ein „unsigned long long“).
„intptr_t“ Dieser Typ beschreibt eine ganze Zahl groß genug um einen Pointer aufzunehmen (x86: 4 Bytes, x64: 8 Bytes).
„float“ (4 Bytes) Reeller Skalar.
„double“ (8 Bytes) Reeller Skalar.
„fcomplex“ (8 Bytes) Komplexer Skalar.
„complex“ (16 Bytes) Komplexer Skalar.
„void*“ Adresse.
„char*“ Adresse oder String-Skalar.
„wchar_t*“ Adresse oder String-Skalar.
„uchar*“ Adresse oder String-Skalar.
„byte*“ Adresse oder String-Skalar.
„short*“ Adresse oder reeller Vektor/Matrix.
„ushort*“ Adresse oder reeller Vektor/Matrix.
„int*“ Adresse oder reeller Vektor/Matrix.
„uint*“ Adresse oder reeller Vektor/Matrix.
„int64*“ Adresse oder reeller Vektor/Matrix.
„uint64*“ Adresse oder reeller Vektor/Matrix.
„float*“ Adresse oder reeller Vektor/Matrix.
„double*“ Adresse oder reeller Vektor/Matrix.
„fcomplex*“ Komplexer Skalar/Vektor/Matrix.
„complex*“ Komplexer Skalar/Vektor/Matrix.

Kommentar

Achtung: Diese Funktion macht nur ganz wenige Fehlerüberprüfungen. Wenn die Funktion falsch aufgerufen wird, kann es zum „Absturz“ von UniPlot kommen.

Beispiel

Der folgende Funktionsaufruf registriert die Funktion FindWindowA die sich in der DLL USER32.DLL befindet. Nach der Registrierung kann die Funktion FindWindowA unter dem Namen _FindWindow von UniScript aus (beliebig oft) aufgerufen werden.

RegisterFunction("USER32", "FindWindowA", "uint", "_FindWindow", ["char*", "char*"]);

Nun kann die Funktion aufgerufen werden. Die Funktion gibt 0 zurück, wenn Excel nicht gestartet wurde und sonst eine Zahl ungleich 0:

h = _FindWindow("XLMAIN", strempty(1,1));

Das folgende Beispiel liefert das aktuelle Verzeichnis:

def GetCurrentDirectory()
{
    ret = RegisterFunction("KERNEL32", "GetCurrentDirectoryW", ..
                           "uint", "GetCurDir", ["uint", "wchar_t*"]);
    ssBuffer = mem_alloc(2048);
    GetCurDir(mem_len(ssBuffer), ssBuffer)
    return ssBuffer;
}

History

Version Beschreibung
5.20 Neuer Typ „intptr_t“. Dieser Typ beschreibt eine ganze Zahl groß genug um einen Pointer aufzunehmen (x86: 4 Bytes, x64: 8 Bytes).
5.10.0 Neue Typen „int64“, „uint64“ und „size_t“.
5.0.0 Neuer Typ „wchar_t“.
4.2.0 Bei svParamTypes gibt es den zusätzlichen Typ byte*. Im Gegensatz zu char* und uchar*, wird das Ergebnis nicht am ersten „\x00“-Zeichen abgeschnitten.

Kommentar

Die UniPlot 64-Bit-Version verwendet die libffi - a portable foreign function interface library. Hier die copyright-Bestimmungen:

ffi.c - Copyright (c) 1996, 1998, 1999, 2001  Red Hat, Inc.
Copyright (c) 2002  Ranjit Mathew
Copyright (c) 2002  Bo Thorsen
Copyright (c) 2002  Roger Sayle

x86 Foreign Function Interface

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
``Software''), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL CYGNUS SOLUTIONS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

id-30251