ArcGIS Desktop

  • ArcGIS Pro
  • ArcMap

  • My Profile
  • 帮助
  • Sign Out
ArcGIS Desktop

ArcGIS Online

专为贵组织打造的制图平台

ArcGIS Desktop

全面的专业性 GIS

ArcGIS Enterprise

面向企业的 GIS

ArcGIS Developers

用于构建位置感知应用程序的工具

ArcGIS Solutions

适用于行业的免费模板地图和应用程序

ArcGIS Marketplace

获取适用于组织的应用程序和数据

  • 文档
  • 支持
Esri
  • 登录
user
  • 我的个人资料
  • 登出

ArcMap

  • 主页
  • 入门
  • 地图
  • 分析
  • 管理数据
  • 工具
  • 扩展模块

通过脚本工具调用 DLL

  • 工作原理
  • 详细信息

Python 2.5 版中新增了 ctypes,它是一种外部函数库。它提供兼容的 C 数据类型,且允许调用 DLL 或共享库中的函数。在 Python 中使用 ctypes 模块使您可在地理处理脚本工具中使用以 C++ 编写的 ArcObjects 代码。

在 Python 中使用 ctypes 使您可以轻松更改脚本工具所需的参数和类型,而不必重新编译 C++ 代码。ctypes 模块支持所有参数为基本数据类型的可调用 C 函数,这些基本数据类型包括 char、int、float、double、structs 和指针等。

通过 Python 脚本调用 DLL 的优点很多。您可以在地理处理任务中使用细化的 ArcObjects 类,您的知识产权是受保护的,而且与必须使用 IGPFunction2 和 IGPFunctionFactory 接口相比执行起来更加简单快捷。只需使用 Python 创建对象并调用执行方法,然后即可通过地理处理框架从脚本传递所需的参数。

工作原理

具体步骤如下:

使用 Visual Studio 2008 创建一个 C++ Win32 项目,该项目通过原型导出一个简单函数:

int GpExecutetool(char* parameter1, char* parameter2)

务必在项目中包括 ArcGIS\com\directory 并导入 ArcObjects .olb 文件。

在自定义工具箱中创建一个脚本工具,用于验证两个参数并将它们传递到脚本中。

Python 脚本将执行以下操作:

  • 导入 arcpy 和 ctypes。
  • 从脚本工具中获取参数。
  • 将 DLL 导入内存。
  • 获取指向 DLL 中函数的指针。
  • 通过设置 argtypes 属性指定从 DLL 中导出的函数所需的参数类型,以及指定返回值的类型。
  • 将参数传递到 DLL 中的 C++ 代码。

详细信息

C++ 项目(本例中名为 GPToolAsSimpleDLL 的项目)是简单的 Win32 项目,该项目可向要素类添加 AREA 字段并计算该字段的值。

头文件

#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*);

GPToolAsSimpleDLL 源文件用于打开指定的面要素类并为每个面要素的面积设置指定的字段。每个编写的地理处理函数均可使用简单的 C 函数入口点执行,并都位于同一个 DLL 中,它们与脚本工具的辅助工具一起将每个函数显示在 ArcToolbox 中。

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;
}

Python 脚本充当的是一个代理,它以文本形式接受脚本工具的两个参数并将其作为 char*(以零结尾的字符串)传递给 DLL 函数。在调用 DLL 中的函数之前,脚本还会使用添加字段地理处理工具。通过使用 C++ 执行专有功能以及使用 Python 执行常见任务使工作流更加稳定。

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

  • 主页
  • 文档
  • 支持

ArcGIS

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

关于 Esri

  • 关于我们
  • 招贤纳士
  • Esri 博客
  • 用户大会
  • 开发者峰会
Esri
分享您的想法。
Copyright © 2021 Esri. | 隐私政策 | 法律声明