首页 > 编程语言 > 详细

eclipse cdt 编译动态库,供msvc调用 -- 2.构建C++动态库工程模板

时间:2020-04-30 10:40:32      阅读:74      评论:0      收藏:0      [点我收藏+]

1. 新建 C/C++ Project >> shared library

技术分享图片

 

 

之前配置了mingw-gcc 这里的 cross gcc 默认指向的就是 mingw path,若没有配置环境变量,也可以手动添加

 

2. 工程属性配置

C/C++ Build

技术分享图片

 

 技术分享图片

 

技术分享图片

 

 

 3. 头文件 条件编译

小生也是初学乍练,场景是这样的,因为使用mingw-gcc 编出的库,可以直接提供给qt 使用,但是vs上就是不能使用,加载后依然无法找到执行函数。

原因是导出函数机制的问题。QT 中报错如:

  error: undefined reference to `_imp__glClearColor@16‘

 

参见代码:

 

 1 /* on MS environments, the inline keyword is available in C++ only */
 2 #if !defined(__cplusplus)
 3 #define inline __inline
 4 #endif
 5 
 6 /* on windows with mingw32 */
 7 #if defined(__GNUC__)
 8 #  define PRE_CDECL
 9 #  define POST_CDECL __attribute__((cdecl))
10 #  define PRE_STDCALL
11 #  define POST_STDCALL __attribute__((stdcall))
12 #  define PRE_FASTCALL
13 #  define POST_FASTCALL __attribute__((fastcall))
14 #else
15 #  define PRE_CDECL __cdecl
16 #  define POST_CDECL
17 #  define PRE_STDCALL __stdcall
18 #  define POST_STDCALL
19 #  define PRE_FASTCALL __fastcall
20 #  define POST_FASTCALL
21 #endif /* __GNUC__ */

 

                                                                                                                                                                                                                                                                            

函数声明:

 1 #if defined(LIBUSP_BPM22_EXPORTS)
 2 #define LIBUSP_BPM22_API __declspec(dllexport)
 3 #else
 4 #define LIBUSP_BPM22_API __declspec(dllimport)
 5 #endif
 6 
 7 #ifdef __cplusplus
 8 extern "C"
 9 {
10 #endif
11 
12     LIBUSP_BPM22_API int PRE_CDECL dll_test(int aa) POST_CDECL;
13 
14 #ifdef __cplusplus
15 }
16 #endif
17 #endif /* LIBUSP_BPM22_H_ */

 

4. 生成对应导入库  dll lib

-- 使用 pexports 导出 def 文件

 技术分享图片

 技术分享图片

 

导出 C++ 文件中的函数,必须将修饰名放到 .def 文件中,或者通过使用外部“C”定义具有标准 C 链接的导出函数。如果需要将修饰名放到 .def 文件中,则可以通过使用 DUMPBIN 工具或 /MAP 链接器选项来获取修饰名。请注意,编译器产生的修饰名是编译器特定的。如果将 Visual C++ 编译器产生的修饰名放到 .def 文件中,则链接到 DLL 的应用程序必须也是用相同版本的 Visual C++ 生成的,这样调用应用程序中的修饰名才能与 DLL 的 .def 文件中的导出名相匹配。
当生成 DLL 时,链接器使用 .def 文件创建导出 (.exp) 文件和导入库 (.lib) 文件。然后,链接器使用导出文件生成 DLL 文件。隐式链接到 DLL 的可执行文件在生成时链接到导入库。在VC++中,如果生成DLL可以不使用.def文件。你只需要在VC++的函数定义前要加 __declspec(dllexport)修饰就可以了。但是使用__declspec(dllexport)和使用.def文件是有区别的。如果你的 DLL是提供给VC++用户使用的,你只需要把编译DLL时产生的.lib提供给用户,它可以很轻松地调用你的DLL。但是如果你的DLL是供VB、 PB、Delphi用户使用的,那么会产生一个小麻烦。因为VC++对于__declspec(dllexport)声明的函数会进行名称转换,如下面的函数:
   __declspec(dllexport) int __stdcall IsWinNT()
会转换为IsWinNT@0,这样你在VB中必须这样声明:
   Declare Function IsWinNT Lib "my.dll" Alias "IsWinNT@0" () As Long
@的后面的数由于参数类型不同而可能不同。这显然不太方便。所以如果要想避免这种转换,就要使用.def文件方式。
EXPORTS后面的数可以不给,系统会自动分配一个数。对于VB、PB、Delphi用户,通常使用按名称进行调用的方式,这个数关系不大,但是对于使用.lib链接的VC程序来说,不是按名称进行调用,而是按照这个数进行调用的,所以最好给出。

== == == ==

针对最简单的Dll,Win32 Application的方式稍有不同,定义导出函数接口的方法有两种:
1.使用__declspce宏
extern "C" __declspec(dllexport) void display(void);
extern "C" __declspec(dllexport) void test(int aa);

这里的extern "C" 表示我们要按照C语言的方式编译该函数,防止在C++工程中编译出现函数名错误,因为C中没有重载而C++中允许重载,所以C++中函数编译后会出现display@1的形式;让编译器以C语言的编译方式编译可以保证C可以调用C++的动态链接库。__declspec(dllexport)表示下来的函数是dll的导出函数接口。没有导出的接口是不可使用的,这里和静态lib库有所区别,静态lib库中的所有函数、宏定义等都是可以使用的。

2.使用def文件,该文件的功能类似于__declspec(dllexport)的功能。

技术分享图片

 

 == == == ==

使用lib pexports 工具导出导入库:

1 pexports libusp_BPM22.dll > libusp_BPM22.def
2 lib.exe /machine:i386 /def:libusp_BPM22.def /out:libusp_bpm22.lib
pexports 是msys 提供的工具
lib 是vs 提供的工具

** 到此,已经得到dll 和对应的导入库 .lib 文件,可以提供给 vs 使用。

 

技术分享图片

 

技术分享图片

 

 

 

参见博文:

https://www.cnblogs.com/chio/archive/2008/11/13/1333119.html

https://www.cnblogs.com/king-lps/p/7757919.html

http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html#Common-Predefined-Macros

DLL中导出函数的两种方式(dllexport与.def文件)

 

eclipse cdt 编译动态库,供msvc调用 -- 2.构建C++动态库工程模板

原文:https://www.cnblogs.com/jk-deamon/p/12801017.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!