ArcGIS Desktop

  • ArcGIS Pro
  • ArcMap

  • My Profile
  • Hilfe
  • Sign Out
ArcGIS Desktop

ArcGIS Online

Die Mapping-Plattform für Ihre Organisation

ArcGIS Desktop

Ein vollständiges professionelles GIS

ArcGIS Enterprise

GIS in Ihrem Unternehmen

ArcGIS Developers

Werkzeuge zum Erstellen standortbezogener Apps

ArcGIS Solutions

Kostenlose Karten- und App-Vorlagen für Ihre Branche

ArcGIS Marketplace

Rufen Sie Apps und Daten für Ihre Organisation ab.

  • Dokumentation
  • Support
Esri
  • Anmelden
user
  • Eigenes Profil
  • Abmelden

ArcMap

  • Startseite
  • Erste Schritte
  • Karte
  • Analysieren
  • Verwalten von Daten
  • Werkzeuge
  • Erweiterungen

Aufrufen einer DLL aus einem Skriptwerkzeug

  • Funktionsweise
  • Details

Neu in Python 2,5 ist das ctypes-Modul, eine Fremdfunktions-Bibliothek. Sie stellt C-kompatible Datentypen bereit und ermöglicht das Aufrufen von Funktionen in DLLs oder freigegebenen Bibliotheken. Mit dem ctypes-Modul in Python kann ArcObjects-Code, der in C++ geschrieben wurde, in einem Geoverarbeitungsskriptwerkzeug verwendet werden.

Wenn Sie ctypes in Python verwenden, können Sie die vom Skriptwerkzeug erwarteten Parameter und Typen leicht ändern, ohne den C++-Code ändern zu müssen. Das Modul ctypes unterstützt jede in C aufrufbare Funktion mit grundlegenden Datentypen wie char, int, float, double und structs sowie Zeiger.

Das Aufrufen einer DLL aus einem Python-Skript bietet eine Reihe von Vorteilen. Sie können komplexe ArcObjects-Classes in Ihren Geoverarbeitungstasks nutzen, Ihr geistiges Eigentum ist geschützt und lässt sich viel leichter implementieren als mit den Schnittstellen IGPFunction2 und IGPFunctionFactory. Erstellen Sie das Objekt in Python, und rufen Sie die execute-Methode auf. Übergeben Sie anschließend die erforderlichen Parameter vom Skript, und verwenden Sie dazu die Geoverarbeitungsumgebung.

Funktionsweise

Die Schritte lauten wie folgt:

Erstellen Sie in Visual Studio 2008 ein Win32-Projekt mit C++, das eine einfache Funktion mit dem Prototyp exportiert:

int GpExecutetool(char* parameter1, char* parameter2)

Stellen Sie sicher, dass Sie "ArcGIS\com\directory" in das Projekt einbeziehen und die .olb-Dateien von ArcObjects importieren.

Erstellen Sie ein Skriptwerkzeug in einer benutzerdefinierten Toolbox, mit dem die beiden Parameter überprüft und an das Skript übergeben werden.

Das Python-Skript führt folgende Aktionen aus:

  • Importieren Sie arcpy und ctypes.
  • Abrufen der Parameter aus dem Skriptwerkzeug
  • Importieren der DLL in den Speicher
  • Abrufen eines Zeigers auf die Funktion in der DLL
  • Angeben der erforderlichen Funktionsargumenttypen, die aus DLLs exportiert wurden, durch Festlegen des argtypes-Attributs und des Rückgabetyps
  • Übergeben der Parameter an den C++-Code in der DLL

Details

Das C++-Projekt ("GPToolAsSimpleDLL" in diesem Beispiel) ist ein einfaches Win32-Projekt, in dem der Feature-Class ein AREA-Feld hinzugefügt und der Wert berechnet wird.

Die Header-Datei

#ifdef GPTOOLASSIMPLEDLL_EXPORTS
#define GPTOOLASSIMPLEDLL_API extern "C"__declspec(dllexport)
#else
#define GPTOOLASSIMPLEDLL_API extern "C"__declspec(dllimport)
#endif
GPTOOLASSIMPLEDLL_API int GPexecutetool(char*, char*);

Die Quelldatei "GPToolAsSimpleDLL" öffnet die angegebene Polygon-Feature-Class und legt das angegebene Feld auf die Fläche der einzelnen Polygon-Features fest. Alle Geoverarbeitungsfunktionen, die Sie schreiben, können mit einem einfachen Einstiegspunkt für eine C-Funktion implementiert werden, alle in der gleichen DLL, sowie mit Zusätzen für Skriptwerkzeuge, die die einzelnen Funktionen für ArcToolbox verfügbar machen.

GPTOOLASSIMPLEDLL_API int GPexecutetool(char* featureclassPath, char* fieldname)
{
    // Convert char*s to bstring
    _bstr_t catalogPath;
    catalogPath = featureclasspath;
    _bstr_t newfieldname;
    newfieldname = fieldname;
    // Coinitialize GP utilities class
    IGPUtilitiesPtr ipUtil(CLSID_GPUtilities);
    // Feature class holder
    IFeatureClassPtr ipFeatureclass(0);
    HRESULT hr;
    // Try to fetch feature class from catalog path
    if (FAILED(hr = ipUtil->OpenFeatureClassFromString(catalogPath, &ipFeatureclass)))
    {
        return -1;
    }
    // Index position of the specified field
   	long fieldIndex;
   	ipFeatureclass->FindField(newfieldname, &fieldIndex);
    // Set up query filter and feature cursor
   	IQueryFilterPtr ipFilter(CLSID_QueryFilter);
   	IFeatureCursorPtr ipCursor;
   	IFeaturePtr ipRow;
   	IGeometryPtr ipShape;
    // Open search cursor on feature class
   	ipFeatureclass->Search(ipFilter, VARIANT_FALSE, &ipCursor);
    // Iterate
    esriGeometryType gt;
    for (ipCursor->NextFeature(&ipRow);
       		ipRow != NULL;
         ipCursor->NextFeature(&ipRow))
    {
         // Get row's associated geometry
		       ipRow->get_Shape(&ipShape);
		       // Ensure we've got a polygon
		       ipShape->get_GeometryType(&gt);
		       if (gt != esriGeometryPolygon)
			          return -2;
		       // Get area
		       IAreaPtr ipArea(ipShape);
         double area;
		       ipArea->get_Area(&area);
		       // Pop double into a variant
         VARIANT value;
		       value.vt = VT_R8;
		       value.dblVal = area;
		       // Set double variant onto target field
		       ipRow->put_Value(fieldIndex, value);
	       	// Save
	       	ipRow->Store();
    }
    return S_OK;
}

Das Python-Skript fungiert als Broker, indem es die beiden Parameter aus dem Skriptwerkzeug akzeptiert und als char*, durch Null terminierte Zeichenfolgen, an die DLL-Funktion sendet. Das Skript verwendet außerdem das Geoverarbeitungswerkzeug Feld hinzufügen, bevor die Funktion in der DLL aufgerufen wird. Dies kann den Workflow robuster machen, indem die proprietären Funktionen in C++ und die gängigen Tasks in Python implementiert werden.

import arcpy
import ctypes
# Get the parameters from the script tool dialog
#
shp = arcpy.GetParameterAsText(0)
fieldName = arcpy.GetParameterAsText(1)
# See if the field already exists in the feature class.
#   If not, add it.
if len(arcpy.ListFields(shp, fieldName)) == 0:
    arcpy.AddField_management(shp, fieldName, "DOUBLE")
# Import DLL into memory and get a pointer to the function
#   Note: be sure the DLL is in your Python search path 
#
dll = ctypes.cdll.GPToolAsSimpleDLL
perform_function = dll.GPExecutetool
# Tell ctypes the function accepts two char* arguments
#
perform_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
# Tell ctypes the function return type
#
perform_function.restype = ctypes.c_int
# Call the function in the DLL
#
retval = perform_function(shp, fieldName)
# Check the return value.  If a 0 returned, success!
#
if retval == 0:
    arcpy.AddMessage("Success")
elif retval == 1:
    arcpy.AddError("Unable to open " + shp)
elif retval == 2:
    arcpy.AddError("Not a polygon feature class")

ArcGIS Desktop

  • Startseite
  • Dokumentation
  • Support

ArcGIS

  • ArcGIS Online
  • ArcGIS Desktop
  • ArcGIS Enterprise
  • ArcGIS
  • ArcGIS Developer
  • ArcGIS Solutions
  • ArcGIS Marketplace

Über Esri

  • Über uns
  • Karriere
  • Esri Blog
  • User Conference
  • Developer Summit
Esri
Wir sind an Ihrer Meinung interessiert.
Copyright © 2021 Esri. | Datenschutz | Rechtliches