Python 使用 numpy 和 gdal 的 C 扩展在运行时给出未定义的符号
Python C Extension using numpy and gdal giving undefined symbol at runtime
我正在为 python 编写 C++ 扩展,以加速内部创建的光栅图像查看器。
我有可用的代码,但注意到速度并没有增加那么多,在更深入地分析之后我意识到这是由于 gdal.ReadAsArray 调用,这是来自 C 扩展的 python 回调.
为了在调用 python 对象时绕过 Python C-API 的开销,我决定使用 gdal 的 C++ 库,而不是使用对现有 gdalDataset 的 Python 回调. (space 不是问题)。
但是,在实现此代码后,我 运行 在 运行 时出错(扩展编译正常)
这是
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 并且出现错误 stull(只是刚刚注意到)。
编辑 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扩展模块是一个可动态加载(共享)的库。当 linking 共享库时,您需要指定其库依赖项,例如 -lgdal
,就此而言,-lpython2.7
。如果不这样做会导致库中有未解析的符号,如果这些符号在加载时未提供,加载将失败,如 Python.
所报告
要解决该错误,您需要将 libraries=['gdal']
添加到 Extension
构造函数。在 extra_compile_args
中指定 -lgdal
将不起作用,因为顾名思义,编译参数用于编译而不是用于 linking。
请注意,在 link 执行可执行文件时未检测到未解析的符号,构建将失败并出现 linker 错误。要在 linking 共享库时获得相同的诊断,请在 link 参数中包含 -Wl,-zdefs
。
我正在为 python 编写 C++ 扩展,以加速内部创建的光栅图像查看器。 我有可用的代码,但注意到速度并没有增加那么多,在更深入地分析之后我意识到这是由于 gdal.ReadAsArray 调用,这是来自 C 扩展的 python 回调. 为了在调用 python 对象时绕过 Python C-API 的开销,我决定使用 gdal 的 C++ 库,而不是使用对现有 gdalDataset 的 Python 回调. (space 不是问题)。 但是,在实现此代码后,我 运行 在 运行 时出错(扩展编译正常)
这是
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 并且出现错误 stull(只是刚刚注意到)。
编辑 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扩展模块是一个可动态加载(共享)的库。当 linking 共享库时,您需要指定其库依赖项,例如 -lgdal
,就此而言,-lpython2.7
。如果不这样做会导致库中有未解析的符号,如果这些符号在加载时未提供,加载将失败,如 Python.
要解决该错误,您需要将 libraries=['gdal']
添加到 Extension
构造函数。在 extra_compile_args
中指定 -lgdal
将不起作用,因为顾名思义,编译参数用于编译而不是用于 linking。
请注意,在 link 执行可执行文件时未检测到未解析的符号,构建将失败并出现 linker 错误。要在 linking 共享库时获得相同的诊断,请在 link 参数中包含 -Wl,-zdefs
。