使用 numpy 和 gdal 的 Python C 扩展在运行时给出未定义的符号

Posted

技术标签:

【中文标题】使用 numpy 和 gdal 的 Python C 扩展在运行时给出未定义的符号【英文标题】:Python C Extension using numpy and gdal giving undefined symbol at runtime 【发布时间】:2016-01-25 17:40:21 【问题描述】:

我正在为 python 编写一个 C++ 扩展来加速内部创建的光栅图像查看器。 我有工作代码,但注意到速度并没有增加那么多,在深入分析后意识到这是由于 gdal.ReadAsArray 调用,这是来自 C 扩展的 python 回调。 为了在调用 python 对象时绕过 Python C-API 的开销,我决定将 C++ 库用于 gdal,而不是对现有 gdalDataset 使用 Python 回调。 (空间不是问题)。 然而,在实现了这个代码之后,我在运行时遇到了一个错误(扩展编译得很好)

这是

 import getRasterImage_new
 ImportError: /local1/data/scratch/lib/python2.7/site-packages
    /getRasterImage_new.so: undefined symbol: _ZN11GDALDataset14GetRasterYSizeEv

下面的代码复制了错误(可能需要在您的机器上运行一些编辑(忽略未初始化的变量,这正是复制错误所需要的)。

Python:

#!/usr/bin/env python
import numpy
from osgeo import gdal
import PythonCTest

print("test starting")
PythonCTest.testFunction(1)
print("test complete")

C++:

#include "Python.h"
#include "numpy/arrayobject.h"
#include "gdal_priv.h"
#include <iostream>

extern "C"
static PyObject* PythonCTest_testFunction(PyObject* args);
static PyMethodDef PythonCTest_newMethods[] = 
   "testFunction", (PyCFunction)PythonCTest_testFunction, METH_VARARGS,
      "test function",
   NULL,NULL,0,NULL;

PyMODINIT_FUNC initPythonCTest(void)
   (void)Py_InitModule("PythonCTest",PythonCTest_newMethods);
   import_array();


GDALDataset* y;
static PyObject* PythonCTest_testFunction(PyObject* args)
   std::cout << "in testFunction\n";
   y->GetRasterYSize();
   std::cout << "doing stuff" << "\n";
   return Py_None;

非常欢迎任何建议。


编辑

您还可以删除 from osgeo import gdal 并发生错误(只是刚刚注意到)。


编辑 2

我忘了说我正在使用 distutils 编译我的扩展

当前 setup.py 是

#!/usr/bin/env python
from distutils.core import setup, Extension
import os
os.environ["CC"] = "g++"
setup(name='PythonCTest', version='1.0', \
   ext_modules=[Extension('PythonCTest', ['PythonCTest.cpp'],
   extra_compile_args=['--std=c++14','-l/usr/include/gdal', '-I/usr/include/gdal'])])

【问题讨论】:

创建扩展时,链接命令中有-lgdal吗? 我没有,我有-Igdal,刚刚尝试过-lgdal,没有任何变化 libraries=['gdal'] 添加到Extension 构造函数调用以确保gdal 用于链接模块(而不是仅用于编译)。 哇哇,这工作.. 谢谢,不敢相信我没有早点尝试过。这个扩展有很多问题。谢谢。如果你把它作为答案,我会标记它。 【参考方案1】:

Python 扩展模块是一个可动态加载(共享)的库。链接共享库时,您需要指定其库依赖项,例如-lgdal-lpython2.7。否则会导致库中包含未解析的符号,如果在加载时未提供这些符号,则加载将失败,正如 Python 所报告的那样。

要解决该错误,您需要将libraries=['gdal'] 添加到Extension 构造函数。在extra_compile_args 中指定-lgdal 将不起作用,因为编译参数,顾名思义,用于编译而不是链接。

请注意,在链接可执行文件时不会检测到未解析的符号,其中构建会因链接器错误而失败。要在链接共享库时获得相同的诊断信息,请在链接参数中包含 -Wl,-zdefs

【讨论】:

以上是关于使用 numpy 和 gdal 的 Python C 扩展在运行时给出未定义的符号的主要内容,如果未能解决你的问题,请参考以下文章

Python遥感图像处理应用篇(十八):GDAL +numpy对遥感图像归一化处理

Python遥感图像处理应用篇(二十三):Python+GDAL 批量拼接图像

Python遥感图像处理应用篇(二十三):Python+GDAL 批量拼接图像

Python GDAL+numpy遥感图像处理过程中背景像元处理方法

Python GDAL+numpy遥感图像处理过程中背景像元处理方法

Python遥感图像处理应用篇(十九):GDAL +numpy批量对遥感图像外围背景值进行处理