openjpeg:解决静态链接时未定义引用错误:undefined reference to `__imp_opj_xxxxxxx‘

20 篇文章 7 订阅

解决办法

加入OPJ_STATIC宏定义。

  1. #include "openjpeg-2.1/openjpeg.h"之前中加入OPJ_STATIC定义,如下
#ifndef OPJ_STATIC
#define OPJ_STATIC
#endif
#include "openjpeg-2.1/openjpeg.h"

2.如果你用cmake编译项目代码可以在CMakeLists.txt中加入OPJ_STATIC定义,类似如下

add_executable(testCImg ${SOURCE_LIST})
##指定使用openjpeg静态库
add_definitions(-DOPJ_STATIC)
target_link_libraries(testCImg "${OPENJP2_LIBRARY_STATIC}" )

=====================================================

问题溯源

如果你希望在项目中以静态库方式使用openjpeg,就要自己动手编译openjpeg的源码,关于如何生成openjpeg静态库参见我之前的博文[《VS2015编译openjpeg(32/64位)》]1和[《mingw(gcc)编译openjpeg》]2

静态库(libopenjp2.a)生成好了,然后编译自己的代码时报错(openjpeg以动态库方式连接(libopenjp2.dll.a),则编译正常通过):

CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x110): undefined reference to __imp_opj_stream_destroy' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x11d): undefined reference to __imp_opj_destroy_codec’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x156): undefined reference to __imp_opj_image_destroy' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x3a9): undefined reference to __imp_opj_stream_create’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x3c8): undefined reference to __imp_opj_stream_set_user_data' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x3ec): undefined reference to __imp_opj_stream_set_user_data_length’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x3fc): undefined reference to __imp_opj_stream_set_read_function' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x40c): undefined reference to __imp_opj_stream_set_write_function’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x41c): undefined reference to __imp_opj_stream_set_skip_function' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x42c): undefined reference to __imp_opj_stream_set_seek_function’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x4b8): undefined reference to __imp_opj_stream_create' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x4d7): undefined reference to __imp_opj_stream_set_user_data’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x4fb): undefined reference to __imp_opj_stream_set_user_data_length' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x50b): undefined reference to __imp_opj_stream_set_read_function’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x51b): undefined reference to __imp_opj_stream_set_write_function' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x52b): undefined reference to __imp_opj_stream_set_skip_function’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x53b): undefined reference to __imp_opj_stream_set_seek_function' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x716): undefined reference to __imp_opj_image_create’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xa44): undefined reference to __imp_opj_set_default_encoder_parameters' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xa60): undefined reference to __imp_opj_create_compress’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xa78): undefined reference to __imp_opj_set_info_handler' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xa8d): undefined reference to __imp_opj_set_warning_handler’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xaa2): undefined reference to __imp_opj_set_error_handler' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xab3): undefined reference to __imp_opj_setup_encoder’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xbc4): undefined reference to __imp_opj_start_compress' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xbdc): undefined reference to __imp_opj_encode’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xbf4): undefined reference to __imp_opj_end_compress' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xc9b): undefined reference to __imp_opj_version’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xfc7): undefined reference to __imp_opj_set_default_encoder_parameters' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x1158): undefined reference to __imp_opj_set_default_encoder_parameters’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x128e): undefined reference to __imp_opj_create_compress' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12a6): undefined reference to __imp_opj_set_info_handler’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12bb): undefined reference to __imp_opj_set_warning_handler' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12d0): undefined reference to __imp_opj_set_error_handler’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12e1): undefined reference to __imp_opj_setup_encoder' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12ee): undefined reference to __imp_opj_stream_create’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x130d): undefined reference to __imp_opj_stream_set_user_data' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x131e): undefined reference to __imp_opj_stream_set_user_data_length’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x132e): undefined reference to __imp_opj_stream_set_read_function' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x133e): undefined reference to __imp_opj_stream_set_write_function’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x134e): undefined reference to __imp_opj_stream_set_skip_function' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x135e): undefined reference to __imp_opj_stream_set_seek_function’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x145a): undefined reference to __imp_opj_start_compress' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x1472): undefined reference to __imp_opj_encode’
CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x148a): undefined reference to __imp_opj_end_compress' CMakeFiles\testCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x15ac): undefined reference to __imp_opj_version’

所有openjpeg的函数都找不到引用。。。。找不到引用的规律是所有的引用前都加了_imp_前缀,比如opj_stream_destroy变成了_img_opj_stream_destroy

满世界百度查资料,只有在这个贴子http://stackoverflow.com/questions/15726931/c-qt-undefined-reference-to-imp结尾处找到一点线索:
这里写图片描述
(IIRC是什么意思还没搞清楚,不去深究了)
编译器在连接的openjpeg时候错误地以连接动态库(DLL)的导入库(import library)的方式去连接静态库,在静态库中找不到具有_imp_前缀的函数名,就报错了.(编译器在生成导入库(import library)时,所有的函数名前都加了_imp_前缀,)
为了证实这个想法用UltraEdit打开openjpeg的动态库(DLL)的导入库(import library)libopenjp2.dll.a(或者别的不相关的导入库都行),以二进制方式查看,果然看到所有openjpeg.h中定义的函数都加了_imp_前缀。
这里写图片描述

现在的问题就是搞清楚,为什么编译器会以连接动态库(DLL)的导入库(import library)的方式去连接openjpeg的静态库,于是仔细研究openjpeg的CMakeLists.txt

发现BUILD_SHARD_LIBS开关控制了两个宏的定义

# Build the library
if(WIN32)
  if(BUILD_SHARED_LIBS)
    add_definitions(-DOPJ_EXPORTS)
  else()
    add_definitions(-DOPJ_STATIC)
  endif()
endif()

打开openjpeg.h找到了用到OPJ_STATICOPJ_EXPORTS的地方:

#if defined(OPJ_STATIC) || !defined(_WIN32)
/* http://gcc.gnu.org/wiki/Visibility */
#if __GNUC__ >= 4
#define OPJ_API    __attribute__ ((visibility ("default")))
#define OPJ_LOCAL  __attribute__ ((visibility ("hidden")))
#else
#define OPJ_API
#define OPJ_LOCAL
#endif
#define OPJ_CALLCONV
#else
#define OPJ_CALLCONV __stdcall
/*
The following ifdef block is the standard way of creating macros which make exporting 
from a DLL simpler. All files within this DLL are compiled with the OPJ_EXPORTS
symbol defined on the command line. this symbol should not be defined on any project
that uses this DLL. This way any other project whose source files include this file see 
OPJ_API functions as being imported from a DLL, wheras this DLL sees symbols
defined with this macro as being exported.
*/
#if defined(OPJ_EXPORTS) || defined(DLL_EXPORT)
#define OPJ_API __declspec(dllexport)
#else
#define OPJ_API __declspec(dllimport)
#endif /* OPJ_EXPORTS */
#endif /* !OPJ_STATIC || !_WIN32 */

上面的代码可以看出如果没有定义OPJ_STATIC,所有的OPJ_API 都会定义成(__declspec(dllexport)__declspec(dllimport)),openjpeg.h定义所有的函数定义都是OPJ_API 开头的,所以都会被定义被定义成DLL调用。

搞清楚原因,解决问题的办法就有了。于是就有了,本文开头的解决方法

jpeg 编解码系列文章

《mingw(gcc)编译libjpeg-turbo》
《libjpeg:实现jpeg内存压缩暨error_exit错误异常处理和个性化参数设置》
《libjpeg:实现jpeg内存解压缩塈转换色彩空间/压缩分辨率》
《libjpeg:读取jpeg头获取图像基本信息(jpeg_read_header)》
《nmake(vs2015)命令行编译libjpeg-turbo(x86/amd64)》

jpeg2000 编码系列文章

《mingw(gcc)编译openjpeg》
《VS2015编译openjpeg(32/64位)》
《openjpeg:解决静态链接时未定义引用错误:undefined reference to `__imp_opj_xxxxxxx‘》
《jpeg2000(j2k)图像编码解码:c++实现openjpeg内存流接口(memory stream)》
《openjpeg:jpeg2000(j2k)图像内存压缩编码》
《openjpeg:jpeg2000(j2k)图像内存解压缩(解码)》
《cmake设置msvc的运行库(runtime library)塈指定openjpeg使用静态库》


  1. http://blog.csdn.net/10km/article/details/50581246 ↩︎

  2. http://blog.csdn.net/10km/article/details/50580841 ↩︎

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

10km

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值