前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >openjpeg:解决静态链接时未定义引用错误:undefined reference to `__imp_opj_xxxxxxx'

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

作者头像
10km
发布2019-05-25 22:04:36
4.2K0
发布2019-05-25 22:04:36
举报
文章被收录于专栏:10km的专栏10km的专栏

版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433585

解决办法

加入**OPJ_STATIC**宏定义。

  1. #include "openjpeg-2.1/openjpeg.h"之前中加入OPJ_STATIC定义,如下
代码语言:javascript
复制
#ifndef OPJ_STATIC
#define OPJ_STATIC
#endif
#include "openjpeg-2.1/openjpeg.h"

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

代码语言:javascript
复制
add_executable(testCImg ${SOURCE_LIST})
##指定使用openjpeg静态库
add_definitions(-DOPJ_STATIC)
target_link_libraries(testCImg "${OPENJP2_LIBRARY_STATIC}" )

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

问题溯源

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

静态库(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开关控制了两个宏的定义

代码语言:javascript
复制
# 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的地方:

代码语言:javascript
复制
#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调用。

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2016年01月28日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 解决办法
  • 问题溯源
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档