python3.6(python-gcc:7.3)-anaconda-写c扩展-undefined symbol:找错误
https://blog.csdn.net/baidu_40840693/article/details/103566759
关于opencv的转换
https://github.com/Algomorph/pyboostcvconverter/blob/master/src/pyboost_cv3_converter.cpp
上次的博客比较乱,这次尽量不乱。。。。。。
扩展库,首先保证cpp库的链接正确,ubuntu来讲,apt-get install libopencv-dev (/usr/lib/x86_64-linux-gnu)
和我自己编译的一个库,因为安装路径写了/usr/local导致可能又安装了一个
cmake -D CMAKE_INSTALL_PREFIX=/usr/local .. (/usr/local/lib)
自己编译的其他版本opencv,修改了 CMAKE_INSTALL_PREFIX的路径,那么又安装了一个,
(/media/spple/新加卷1/opencv-3.4.1/install_4/lib)
导致有很多个版本的opencv在这个电脑上,那么问题来了,python setup.py build应该去哪里找我们想要的opencv
下面是一个简单的python setup.py build的示例
虽然我们可以指定library_dirs,让opencv去我们想要的地方找,但是问题来了,这是一个简单的例子,如果我的library_dirs
from distutils.core import setup, Extension
module1 = Extension('demo',
define_macros = [('MAJOR_VERSION', '1'),
('MINOR_VERSION', '0')],
include_dirs = ['/usr/local/include'],
libraries = ['tcl83'],
library_dirs = ['/usr/local/lib'],
sources = ['main.cpp'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
author = 'Martin v. Loewis',
author_email = 'martin@v.loewis.de',
url = 'https://docs.python.org/extending/building',
long_description = '''This is really just a demo package.''',
ext_modules = [module1])
很复杂呢,复杂到什么程度,上面说的三种情况的opencv地址都包含了
比如下面这种情况:
from distutils.core import setup, Extension
module1 = Extension('demo',
define_macros = [('MAJOR_VERSION', '1'),
('MINOR_VERSION', '0')],
include_dirs = ['/usr/local/include',
#------------make install 默认CMAKE_INSTALL_PREFIX
'/usr/include/opencv','/usr/include/opencv2'
#------------apt-get install libopencv-dev
'/media/spple/新加卷1/opencv-3.4.1/install_4/include'],
#------------make install 修改CMAKE_INSTALL_PREFIX
libraries = ['opencv_core', 'opencv_calib3d',
'opencv_imgproc', 'opencv_imgcodecs',
'opencv_highgui', 'opencv_features2d',
'opencv_cudafilters', 'opencv_cudaimgproc',
'opencv_cudev', 'opencv_features2d',
'opencv_flann', 'opencv_viz',
'opencv_cudawarping','opencv_cudafeatures2d'],
library_dirs = ['/usr/local/lib',
# ------------make install 默认CMAKE_INSTALL_PREFIX
'/usr/lib/x86_64-linux-gnu',
# ------------apt-get install libopencv-dev
'/media/spple/新加卷1/opencv-3.4.1/install_4/lib'],
# ------------make install 修改CMAKE_INSTALL_PREFIX
sources = ['main.cpp'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
author = 'Martin v. Loewis',
author_email = 'martin@v.loewis.de',
url = 'https://docs.python.org/extending/building',
long_description = '''This is really just a demo package.''',
ext_modules = [module1])
编译或者运行的时候,会出现,找不到opencv的错误,那么怎么办
python setup.py build
python steup.py install --record log.txt
Ubuntu等Liunx都有path环境变量的路径,且都有不同的优先级,比如平常教程让我们修改的~/.bashrc
/etc/ld.so.conf.d/opencv.conf
然后刷新:sudo ldconfig -v
那么这么修改其实有时候也会和上述说的冲突,我们现在说一下,怎么修改环境变量,优先级会高于前面说的
apt-get install和make install默认路径的情况
修改:
sudo vim /etc/ld.so.conf
该目录下有:
include /etc/ld.so.conf.d/*.conf
那么这句话对应的会将:
/etc/ld.so.conf.d$ ls cuda.conf opencv.conf fakeroot-x86_64-linux-gnu.conf x86_64-linux-gnu.conf i386-linux-gnu.conf x86_64-linux-gnu_EGL.conf i386-linux-gnu_GL.conf x86_64-linux-gnu_GL.conf libc.conf zz_i386-biarch-compat.conf
下面这些的conf都包含,如果我们在/etc/ld.so.conf 中修改
/media/spple/新加卷1/opencv-3.4.1/install_4/lib include /etc/ld.so.conf.d/*.conf
然后刷新环境变量
sudo ldconfig -v
此时,你会发现,
/media/spple/新加卷1/opencv-3.4.1/install_4/lib的优先级是最高的
以下是我的电脑显示,最前面的部分截取
spple@spple:/etc$ sudo ldconfig -v [sudo] spple 的密码: /sbin/ldconfig.real: 无法对 /lib/i686-linux-gnu 进行 stat 操作: 没有那个文件或目录 /sbin/ldconfig.real: 无法对 /usr/lib/i686-linux-gnu 进行 stat 操作: 没有那个文件或目录 /sbin/ldconfig.real: 多次给出路径“/lib/x86_64-linux-gnu” /sbin/ldconfig.real: 多次给出路径“/usr/lib/x86_64-linux-gnu” /media/spple/新加卷1/opencv-3.4.1/install_4/lib: libopencv_viz.so.3.4 -> libopencv_viz.so.3.4.1 libopencv_imgproc.so.3.4 -> libopencv_imgproc.so.3.4.1 libopencv_imgcodecs.so.3.4 -> libopencv_imgcodecs.so.3.4.1 libopencv_highgui.so.3.4 -> libopencv_highgui.so.3.4.1 libopencv_flann.so.3.4 -> libopencv_flann.so.3.4.1 libopencv_features2d.so.3.4 -> libopencv_features2d.so.3.4.1 libopencv_cudev.so.3.4 -> libopencv_cudev.so.3.4.1 libopencv_cudawarping.so.3.4 -> libopencv_cudawarping.so.3.4.1 libopencv_cudaimgproc.so.3.4 -> libopencv_cudaimgproc.so.3.4.1 libopencv_cudafilters.so.3.4 -> libopencv_cudafilters.so.3.4.1 libopencv_cudafeatures2d.so.3.4 -> libopencv_cudafeatures2d.so.3.4.1 libopencv_cudaarithm.so.3.4 -> libopencv_cudaarithm.so.3.4.1 libopencv_core.so.3.4 -> libopencv_core.so.3.4.1 libopencv_calib3d.so.3.4 -> libopencv_calib3d.so.3.4.1 /usr/local/cuda/lib64: libnppim.so.9.0 -> libnppim.so.9.0.176 libnvrtc.so.9.0 -> libnvrtc.so.9.0.176 libnppitc.so.9.0 -> libnppitc.so.9.0.176 libnppidei.so.9.0 -> libnppidei.so.9.0.176 libcurand.so.9.0 -> libcurand.so.9.0.176 libnppc.so.9.0 -> libnppc.so.9.0.176 libcuinj64.so.9.0 -> libcuinj64.so.9.0.176 libcusolver.so.9.0 -> libcusolver.so.9.0.176 libcublas.so.9.0 -> libcublas.so.9.0.480 libOpenCL.so.1 -> libOpenCL.so.1.0.0 libaccinj64.so.9.0 -> libaccinj64.so.9.0.176 libcufftw.so.9.0 -> libcufftw.so.9.0.176 libnpps.so.9.0 -> libnpps.so.9.0.176 libcudnn.so.7 -> libcudnn.so.7.5.1 libcudart.so.9.0 -> libcudart.so.9.0.176 libnppicc.so.9.0 -> libnppicc.so.9.0.176 libnppist.so.9.0 -> libnppist.so.9.0.176 libnppicom.so.9.0 -> libnppicom.so.9.0.176 libnvToolsExt.so.1 -> libnvToolsExt.so.1.0.0 libnppif.so.9.0 -> libnppif.so.9.0.176 libnppial.so.9.0 -> libnppial.so.9.0.176 libnvrtc-builtins.so.9.0 -> libnvrtc-builtins.so.9.0.176 libnppisu.so.9.0 -> libnppisu.so.9.0.176 libnvblas.so.9.0 -> libnvblas.so.9.0.480 libnppig.so.9.0 -> libnppig.so.9.0.176 libnvgraph.so.9.0 -> libnvgraph.so.9.0.176 libcusparse.so.9.0 -> libcusparse.so.9.0.176 libcufft.so.9.0 -> libcufft.so.9.0.176 /usr/lib/x86_64-linux-gnu/libfakeroot: libfakeroot-0.so -> libfakeroot-tcp.so
ok解决问题
期间还有一个问题:
terminate called after throwing an instance of 'cv::Exception'
what(): OpenCV(4.1.2) ../modules/core/include/opencv2/core/private.cuda.hpp:109: error: (-216:No CUDA support) The library is compiled without CUDA support in function 'throw_no_cuda'
出现这种愿意,不是c++库的问题了,而是anaconda中的python问题:
我们在/目录下进行find搜索:
发现:
/home/spple/anaconda3/pkgs
下有:
目录:
libopencv-4.1.2-h6185dc4_0
opencv-4.1.2-0
py-opencv-4.1.2-py36h5ca1d4c_0
和
libopencv-4.1.2-h6185dc4_0.tar.bz2
opencv-4.1.2-0.tar.bz2
py-opencv-4.1.2-py36h5ca1d4c_0.tar.bz2
我理解的是,这是我们使用pip install安装时候留下了的,但是发现只有opencv4.1.2出现了这个,具体原因暂时不知
有py-opencv的,有cpp-opencv的
我是把他们全删除了
还有我自己的环境下,也就是编译c++扩展库的环境:
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib
也有很多opencv的lib,这些是因为安装opencv-python和opencv-contrib-python留下来的,但是发现只有opencv4.1.2出现了这个,具体原因暂时不知
使用命令删除:
rm -rf libopencv_*.so.4*
rm -rf libopencv_*
还有
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/conda-meta下的
libopencv-4.1.2-h6185dc4_0.json
py-opencv-4.1.2-py36h5ca1d4c_0.json
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/pkgconfig下的
opencv4.pc
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/share下的
opencv4
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/share/licenses下的
opencv4
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/cmake下的(这个不删除,他是cmake的)
opencv4
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/bin下的
opencv_annotation*
opencv_interactive-calibration*
opencv_version*
opencv_viewer_example.py*
opencv_visualisation*
opencv_waldboost_detector*
删除他们:
rm -rf opencv_*
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/bin下的
setup_vars_opencv4.sh
顺便查看下:
echo $LD_LIBRARY_PATH 还有没有opencv
和:
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/python3.6/site-packages
做完这些后,重新为python安装其他版本的opencv
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/bin/pip install opencv-python==3.4.2.17
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/bin/pip install opencv-contrib-python==3.4.2.17
装完以后就像前面红字说的,并没有出现我们刚刚删除的这些的3.4.2版本的相应东西,好吧,我也不知道为啥这样,真玄学
然后我们重新编译:
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/bin/python setup.py build
anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/bin/python steup.py install --record log.txt
好吧又重新新问题:
ImportError: /home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/libharfbuzz.so.0: undefined symbol: FT_Done_MM_Var
定位这个包:
locate libharfbuzz.so.0
发现其他地方也有,按照网上的说法我安装的这个有问题:
/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/libharfbuzz.so.0
/home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/libharfbuzz.so.0.20400.0
/home/spple/anaconda3/lib/libharfbuzz.so.0
/home/spple/anaconda3/lib/libharfbuzz.so.0.10706.0
/home/spple/anaconda3/pkgs/harfbuzz-1.7.6-h5f0a787_1/lib/libharfbuzz.so.0
/home/spple/anaconda3/pkgs/harfbuzz-1.7.6-h5f0a787_1/lib/libharfbuzz.so.0.10706.0
/home/spple/anaconda3/pkgs/harfbuzz-2.4.0-h9f30f68_3/lib/libharfbuzz.so.0
/home/spple/anaconda3/pkgs/harfbuzz-2.4.0-h9f30f68_3/lib/libharfbuzz.so.0.20400.0
/usr/lib/x86_64-linux-gnu/libharfbuzz.so.0
/usr/lib/x86_64-linux-gnu/libharfbuzz.so.0.10000.1
先备份好原来的
我把/usr/lib/x86_64-linux-gnu下的
libharfbuzz.a
libharfbuzz.so
libharfbuzz.so.0
libharfbuzz.so.0.10000.1
复制替换到pytorch1_1_0--py3_6--cuda9_0/lib/ 解决但是新error,我严重怀疑他们是一伙的,同样方法
ImportError: /home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/libfontconfig.so.1: undefined symbol: FT_Done_MM_Var
ImportError: /home/spple/anaconda3/envs/pytorch1_1_0--py3_6--cuda9_0/lib/libcairo.so.2: undefined symbol: FT_Get_Var_Design_Coordinates
说实话,我觉得这样做下去肯定不对,我重新新建一个anaconda的环境,看看,是否从开始就有这些,并且用新环境编译
他很新,只有cpython numpy opencv,我观察了,确实没有oepncv4.1.2那些乱七八糟的
anaconda3/envs/py36_cpp_extension/bin/python -mpip list
Package Version
--------------------- -------------------
certifi 2019.11.28
chardet 3.0.4
Cython 0.29.14
idna 2.8
numpy 1.18.0
opencv-contrib-python 3.4.2.17
opencv-python 3.4.2.17
pip 19.3.1
pymongo 3.10.0
requests 2.22.0
setuptools 44.0.0.post20200102
urllib3 1.25.7
wheel 0.33.6
好吧,果然,成功了:
没有任何错误,我就在思考,是什么,把上一个环境弄得乱七八糟的,是不是opencv4.1.2呢?????
我决定尝试一下,使用pip安装opencv4.1.2
擦没有竟然,我冤枉pip install opencv-python了
那么到底是谁整出了那么多东西
继续找,我想了想,我还安装过mmcv和mmdetection,这两个和opencv有关,继续
mmcv测试了没有影响
好吧,算了算了,原谅你的出现了
接着我们说
python setup.py build
现在有这么一个需求,
其他3个功能要写在.h .cpp中
然后还有一个总的main.cpp作为包
那么在main.cpp
中是:
// 联合编程包
#include <Python.h>
#include <numpy/arrayobject.h>
static PyObject * YNHICP(PyObject *self, PyObject *args) {
PyObject *image1, *image2;
PyObject *pList1;
PyObject *pList2;
PyObject *pList3;
if (!PyArg_ParseTuple(args, "OOO!O!O!", &image1, &image2, &PyList_Type, &pList1,&PyList_Type, &pList2,&PyList_Type, &pList3)) {
PyErr_SetString(PyExc_TypeError, "parameter3 must be a list.");
return NULL;
}
std::vector<string> namelist;
PyObject *pItem1;
Py_ssize_t n1;
n1 = PyList_Size(pList1);
for (int i=0; i<n1; i++) {
pItem1 = PyList_GetItem(pList1, i);
if(!PyUnicode_Check(pItem1)) {
PyErr_SetString(PyExc_TypeError, "list items must be String.");
return NULL;
}
string key = PyUnicode_AsUTF8(pItem1);
namelist.push_back(key);
}
PyObject *pItem2;
Py_ssize_t n2;
n2 = PyList_Size(pList2);
for (int i=0; i<n2; i++) {
pItem2 = PyList_GetItem(pList2, i);
if(!PyUnicode_Check(pItem2)) {
PyErr_SetString(PyExc_TypeError, "list items must be String.");
return NULL;
}
string key = PyUnicode_AsUTF8(pItem2);
namelist.push_back(key);
}
PyObject *pItem3;
Py_ssize_t n3;
n3 = PyList_Size(pList3);
for (int i=0; i<n3; i++) {
pItem3 = PyList_GetItem(pList3, i);
if(!PyUnicode_Check(pItem3)) {
PyErr_SetString(PyExc_TypeError, "list items must be String.");
return NULL;
}
string key = PyUnicode_AsUTF8(pItem3);
namelist.push_back(key);
}
int count = namelist.size();
for (int i = 0; i < count;i++)
{
std::cout << namelist[i] << std::endl;
}
PyObject* retval;
retval = (PyObject *)Py_BuildValue("i", 1000);
return retval;
}
static PyMethodDef
YNHICPMethods[] = {
{"ICP", YNHICP, METH_VARARGS},
{NULL, NULL},
};
static struct PyModuleDef YNHICPModule = {
PyModuleDef_HEAD_INIT,
"YNHICP",
NULL,
-1,
YNHICPMethods
};
PyMODINIT_FUNC PyInit_YNHICP(void)
{
return PyModule_Create(&YNHICPModule);
}
其他3组和cpp语法一样,.h声明类或者函数;.cpp实现类内函数,或.h声明函数
然后,
setup.py中:
把哪些.h的包,路径放入,假设全部都在
/home/spple/ynh/include :fun1.h,fun2.h,fun3.h
其他的cpp和mian.py放在一起,那么如下:
比如fun1.cpp,fun2.cpp,fun3.cpp
from distutils.core import setup, Extension
module1 = Extension('demo',
define_macros = [('MAJOR_VERSION', '1'),
('MINOR_VERSION', '0')],
include_dirs = ['/usr/local/include', '/home/spple/ynh/include'],
libraries = ['tcl83'],
library_dirs = ['/usr/local/lib'],
sources = ['mian.cpp','fun1.cpp','fun3.cpp','fun2.cpp'])
setup (name = 'PackageName',
version = '1.0',
description = 'This is a demo package',
author = 'Martin v. Loewis',
author_email = 'martin@v.loewis.de',
url = 'https://docs.python.org/extending/building',
long_description = '''This is really just a demo package.''',
ext_modules = [module1])