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

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'

参见代码:

/* on MS environments, the inline keyword is available in C++ only */
#if !defined(__cplusplus)
#define inline __inline
#endif

/* on windows with mingw32 */
#if defined(__GNUC__)
#  define PRE_CDECL
#  define POST_CDECL __attribute__((cdecl))
#  define PRE_STDCALL
#  define POST_STDCALL __attribute__((stdcall))
#  define PRE_FASTCALL
#  define POST_FASTCALL __attribute__((fastcall))
#else
#  define PRE_CDECL __cdecl
#  define POST_CDECL
#  define PRE_STDCALL __stdcall
#  define POST_STDCALL
#  define PRE_FASTCALL __fastcall
#  define POST_FASTCALL
#endif /* __GNUC__ */

函数声明:

#if defined(LIBUSP_BPM22_EXPORTS)
#define LIBUSP_BPM22_API __declspec(dllexport)
#else
#define LIBUSP_BPM22_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C"
{
#endif

    LIBUSP_BPM22_API int PRE_CDECL dll_test(int aa) POST_CDECL;

#ifdef __cplusplus
}
#endif
#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 使用。

参见博文:

分析Linux和windows动态库 - 中土 - 博客园

GCC编译过程与动态链接库和静态链接库 - 三年一梦 - 博客园

Common Predefined Macros (The C Preprocessor)

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值