VC 中如何使用 BCB 编译的库文件

在 Visual C++ 或者 Visual Studio 中, 是无法直接使用 BCB 工程编译产生的库文件的. 究其原因, 是由于微软 Visual C++ lib 文件格式与 BCB 工程的 lib 文件格式不同所导致. Lib 文件中存放的是动态链接库的接口信息, 而不会含有任何函数的内部实现细节. 因此, 我们可以直接通过 Dll 文件来反向生成特定格式的 lib 文件, 以便在 VC 和 BCB 中交叉使用各个编译的动态链接库.

以 MTK 平台的多路下载工具 SP_MDT 为例, 演示在 VC++ 中直接使用 BCB 编译的 lib 库的问题及解决方案. 我们以 Eboot 为例, 源代码目录下关于 Eboot 的文件有以下几个:
Eboot 头文件定义, 路径: SP_MDT_SRC\Eboot
Eboot lib 库文件, 路径: SP_MDT_SRC\Lib
Eboot 动态链接库文件, 路径: SP_MDT_SRC\output

我们新建一个 VC++ MFC 工程, 将上述文件全部拷贝到 MFC 工程目录下, 同时在对话框中实现如下代码段:

#include "interface.h"
ANDROID_DL_HANDLE_T handle;
Android_DL_Create(&handle);

此时, 编译工程会报出如下错误:

error LNK2019: 无法解析的外部符号 _Android_DL_Create@4
该符号在函数 "public: void __thiscall CLibDemoDlg::OnBnClickedOk(void)" 中被引用

原因在于我们仅仅包含了相应函数的头文件, 而并没有导入任何的函数实现(如 cpp 源文件或者 lib 库文件). 接下来, 我们尝试直接在 VC++ 中使用 BCB 编译生成的 lib 库文件, 加入以下代码:

#pragma comment(lib, "eboot.lib")

编译时报出如下错误:

eboot.lib : warning LNK4003: 无效的库格式; 已忽略库

显然, VC++ 并不能正确的识别 BCB 所生成的 lib 库文件. 那么如何解决这个问题呢? 一般来说有两种方法:

  1. 动态加载 dll 动态链接库
    最直接的方法是, 既然有头文件, 那么就可以知道各个函数的定义, 而 dll 动态链接库则会将这些公开的函数导出. 因此, 可以直接调用 LoadLibrary 载入动态链接库, 并查找到相应的函数地址, 完成调用. 这种方法简单粗暴, 其好处是写出的源代码无论是在 BCB 还是在 VC++ 平台都能够通用. 但其缺点也很明显, 需要改写头文件, 定义各种各样的函数指针, 如果使用到的导出函数很多, 则工作量较大.
  2. 使用 VC++ 编译工具生成 lib 文件
    那么既然原有的工程提供了头文件, 为了最大程度的减少工作量, 可以通过 BCB 生成的 dll 反向输出 VC++ 的 lib 文件, 实现静态加载 dll 动态链接库. 方法如下:
    (1) 使用 dumpbin 生成 .def 文件
    dumpbin 位于 [VS_DIR]\VC\bin 目录中, 执行如下命令产生 .def 文件:
dumpbin eboot.dll /EXPROTS /OUT:eboot.def

此时, eboot.def 文件内容为:

Dump of file E:\eboot.dll
File Type: DLL
  Section contains the following exports for eboot.dll
    00000000 characteristics
    4E3F5BF7 time date stamp Mon Aug 08 11:45:59 2011
        0.00 version
           1 ordinal base
         101 number of functions
          44 number of names
 
    ordinal hint RVA      name
         49    0 000021F0 Android_ADV_Connect
         41    1 00001000 Android_ADV_Create
         42    2 00001150 Android_ADV_Destory
         47    3 00001B00 Android_ADV_FreeBuffer
         46    4 000015D0 Android_ADV_LoadBuffer
         51    5 00002A00 Android_ADV_Reboot
         48    6 00001B30 Android_ADV_SendBuffer
         50    7 00002640 Android_ADV_SendImage
         43    8 000011D0 Android_ADV_SetBootArg
         44    9 00001340 Android_ADV_SetDownloadArg
         45    A 000015A0 Android_ADV_SetRemoteArg
         13    B 00002FD0 Android_Boot_As_Download
         18    C 00003150 Android_DA_Download
         31    D 00003420 Android_DL_Create
         32    E 000034E0 Android_DL_Destroy
         33    F 00003550 Android_DL_Rom_Load
         34   10 00003B20 Android_DL_Rom_UnloadAll
         14   11 00003080 Android_Flash_Download
         35   12 00003B60 Android_Remote_Download
         71   13 00003C30 Android_Secured_Download
         15   14 00003330 Android_Set_Lock
         19   15 00003240 Android_Write_Trace
          9   16 000140B0 CloseActiveSync
        101   17 00010940 Eboot_DebugChangePath
          4   18 00010910 Eboot_DebugClear
          3   19 00010900 Eboot_DebugOff
          5   1A 000108F0 Eboot_DebugOn
          6   1B 00010920 Eboot_GetDLLInfo
         12   1C 000108C0 Eboot_Log
         64   1D 000154E0 GetAllDeviceNumber
         63   1E 000155F0 GetAllPresentDevicePath
         62   1F 000158B0 GetDeviceNumber
         65   20 00016400 GetPortsDriverVersion
         61   21 000159D0 GetPresentDevicePath
         10   22 000140E0 RestartActiveSync
         16   23 0000F2D0 SP_BootAsAdvmeta
         21   24 0000F680 SP_BootAsAdvmetaByUSB
          7   25 0000FA60 SP_BootAsFactoryNormalMode
         20   26 0000FDD0 SP_BootAsFactoryNormalModeByUSB
          2   27 0000EB70 SP_BootAsMeta
         17   28 0000EF00 SP_BootAsMetaByUSB
         11   29 00011260 SP_Flash_Direct_Download
          1   2A 000111C0 SP_Flash_Download
          8   2B 00013EF0 SP_MPDownload
  Summary
      106000 .data
        4000 .rdata
        3000 .reloc
        1000 .rsrc
       18000 .text

(2) 为 .def 文件添加 lib 说明
在 .def 文件开头处加入如下描述:

LIBRARY "eboot"

(3) 整理 .def 中的 EXPORT 信息
删除除 EXPORTS 段以外的其他无用信息, 同时根据头文件将 EXPORTS 段的 ordinal 和 name 字段进行整理:

  • 如果是 stdcall 调用, 则整理为 name@param_size @ordinal 的形式; 注意, name 和 param size 之间不能有空格.
  • 如果是 cdecl 调用, 则整理为 name@ordinal 的形式;

例如, Android_DL_Create 的定义为:

extern int __stdcall Android_DL_Create(ANDROID_DL_HANDLE_T *p_dl_handle);

可以看到该函数是一个 stdcall 调用, 其参数为 1 个指针, 占用 4 个字节, 因此整理为如下形式:

EXPORTS ...... Android_DL_Create@4 @31

(4) 根据 .def 生成 .lib 文件
在 .def 文件整理完毕之后, 使用 lib.exe 生成 .lib 文件, 执行如下命令:

lib /def:eboot.def /machine:i386 /out:eboot.lib

即可生成 eboot.exp 和 eboot.lib 文件. 将 eboot.lib 文件拷贝到 MFC 工程目录下替换原有的 lib 文件,
并重新编译, 通过. 将 eboot.dll 拷贝到与 exe 相同路径下, 运行正常.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,398评论 25 707
  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 7,774评论 0 27
  • 动态调用动态库方法c/c++linuxwindows 关于动态调用动态库方法说明 一、 动态库概述 1、 动态库的...
    KINGZ1993阅读 13,880评论 0 10
  • 值和引用类型 值语义 所以 str 的值并没有改变。因为字符串是一个结构体, 而结构体是值类型。那什么是值类型呢?...
    焉知非鱼阅读 338评论 0 0
  • 爱情不应该是遇到“合适”的人才开始的,我觉得爱情应该是遇到自己想要开始的那个人,努力让那个人成为“合适”。——随心所写
    茹G阅读 129评论 0 0