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])
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐