openjpeg:解决静态链接时未定义引用错误:undefined reference to `__imp_opj_xxxxxxx'
版权声明:本文为博主原创文章,转载请注明源地址。 https://blog.csdn.net/10km/article/details/50598753
解决办法
加入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位)》和《mingw(gcc)编译openjpeg》
静态库(libopenjp2.a)生成好了,然后编译自己的代码时报错(openjpeg以动态库方式连接(libopenjp2.dll.a),则编译正常通过):
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x110): undefined reference to
__imp_opj_stream_destroy'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x11d): undefined reference to
__imp_opj_destroy_codec’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x156): undefined reference to__imp_opj_image_destroy'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x3a9): undefined reference to
__imp_opj_stream_create’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x3c8): undefined reference to__imp_opj_stream_set_user_data'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x3ec): undefined reference to
__imp_opj_stream_set_user_data_length’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x3fc): undefined reference to__imp_opj_stream_set_read_function'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x40c): undefined reference to
__imp_opj_stream_set_write_function’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x41c): undefined reference to__imp_opj_stream_set_skip_function'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x42c): undefined reference to
__imp_opj_stream_set_seek_function’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x4b8): undefined reference to__imp_opj_stream_create'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x4d7): undefined reference to
__imp_opj_stream_set_user_data’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x4fb): undefined reference to__imp_opj_stream_set_user_data_length'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x50b): undefined reference to
__imp_opj_stream_set_read_function’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x51b): undefined reference to__imp_opj_stream_set_write_function'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x52b): undefined reference to
__imp_opj_stream_set_skip_function’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x53b): undefined reference to__imp_opj_stream_set_seek_function'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x716): undefined reference to
__imp_opj_image_create’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xa44): undefined reference to__imp_opj_set_default_encoder_parameters'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xa60): undefined reference to
__imp_opj_create_compress’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xa78): undefined reference to__imp_opj_set_info_handler'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xa8d): undefined reference to
__imp_opj_set_warning_handler’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xaa2): undefined reference to__imp_opj_set_error_handler'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xab3): undefined reference to
__imp_opj_setup_encoder’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xbc4): undefined reference to__imp_opj_start_compress'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xbdc): undefined reference to
__imp_opj_encode’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xbf4): undefined reference to__imp_opj_end_compress'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xc9b): undefined reference to
__imp_opj_version’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0xfc7): undefined reference to__imp_opj_set_default_encoder_parameters'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x1158): undefined reference to
__imp_opj_set_default_encoder_parameters’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x128e): undefined reference to__imp_opj_create_compress'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12a6): undefined reference to
__imp_opj_set_info_handler’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12bb): undefined reference to__imp_opj_set_warning_handler'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12d0): undefined reference to
__imp_opj_set_error_handler’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12e1): undefined reference to__imp_opj_setup_encoder'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x12ee): undefined reference to
__imp_opj_stream_create’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x130d): undefined reference to__imp_opj_stream_set_user_data'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x131e): undefined reference to
__imp_opj_stream_set_user_data_length’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x132e): undefined reference to__imp_opj_stream_set_read_function'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x133e): undefined reference to
__imp_opj_stream_set_write_function’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x134e): undefined reference to__imp_opj_stream_set_skip_function'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x135e): undefined reference to
__imp_opj_stream_set_seek_function’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x145a): undefined reference to__imp_opj_start_compress'
CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x1472): undefined reference to
__imp_opj_encode’ CMakeFilestestCImg.dir/objects.a(j2k_mem.cpp.obj):j2k_mem.cpp:(.text+0x148a): undefined reference to__imp_opj_end_compress'
CMakeFilestestCImg.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_STATIC
和OPJ_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调用。
搞清楚原因,解决问题的办法就有了。于是就有了,本文开头的解决方法
- 关于查看dba_data_files的一个小问题(r7笔记第72天)
- 一则备库CPU报警的思考(r7笔记第69天)
- Java设计模式-观察者模式
- 今天处理的三个小问题——20160120(r7笔记第84天)
- 主备切换的准备工作(r7笔记第83天)
- Java设计模式-外观模式
- Java设计模式-组合模式
- 使用shell批量监控磁盘坏块(二) (r7笔记第80天)
- JavaWeb10-request&response你不得不学(1)
- dg的奇怪问题终结和分区问题答疑 (r7笔记第77天)
- 最近让我焦灼的四个问题(有解) (r7笔记第76天)
- JavaWeb10-reques;response你不得不学(2)
- 很多人比较纠结的约束和索引的关系(r7笔记第75天)
- JavaWeb09-Servlet(Java真正的全栈开发)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 在Python中使用Torchmoji将文本转换为表情符号
- 我通过三个故事终于学明白了三种工厂模式
- 《设计模式》系列-SOLID设计原则
- (力扣)面试题56 - I. 数组中数字出现的次数
- 玩转 Java8 中的 Stream 之从零认识 Stream
- 聊聊dubbo-go的DubboInvoker
- 剑指Offer 面试题03. 数组中重复的数字
- SDAccel矩阵乘法优化(一)
- 花式玩 Spring Security ,这样的用户定义方式你可能没见过!
- 一文胜千言的DHCP的讲解以及DHCP服务器的配置
- 小知识 词云制作
- 解决 Error starting userland proxy: listen tcp 0.0.0.0:6379: bind: address already in use
- Qt官方示例-菜单栏
- 解决SpringBoot集成支付宝支付中文订单描述验签错误问题
- Linux挂载