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

Python C Extension using numpy and gdal giving undefined symbol at runtime

本文关键字:运行时 未定义 符号 gdal 扩展 numpy Python      更新时间:2023-10-16

我正在为 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

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

蟒:

#!/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 testFunctionn";
   y->GetRasterYSize();
   std::cout << "doing stuff" << "n";
   return Py_None;
}

任何建议将非常受欢迎。


编辑

您也可以从osgeo导入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'])])

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

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

请注意,链接

可执行文件时不会未检测到未解析的符号,其中生成将失败并显示链接器错误。要在链接共享库时获得相同的诊断,请在链接参数中包含-Wl,-zdefs