`
923723914
  • 浏览: 636466 次
文章分类
社区版块
存档分类
最新评论

从DLL生成LIB

 
阅读更多

从DLL生成LIB

cheungmine

2013-5-14

windows程序链接到一个动态链接库.dll时需要一个导入库.lib。遗憾的是这样的导入库很多时候是不存在的,那么就需要我们自己从.dll生成对应的导入库.lib。假设我们的windows程序为WinApp.exe,它静态链接到一个动态库libABC.dll。我们在WinApp.exe的源代码中可以这样写:

// (程序清单1)
// WinApp.c
//

#include <windows.h>

#include "C:/DEVPACK/LIBABC/include/ABCapi.h"
# pragma comment(lib, "C:/DEVPACK/LIBABC/lib/libABC.lib");

int main()
{
    // 下面可以直接使用 LIBABC 的函数
    ABCInit();
    ABCAddValues(a, b);
    ABCUninit();

    exit(0);
}
但是问题是,我们手里只有libABC.dll和头文件。没有libABC.lib。这就需要我们从命令行工具生成出libABC.lib。从DLL生成LIB的过程是:DLL->DEF->LIB。需要生成一个叫做模块定义文件(.def)的中间文件。一个典型的模块定义文件(libABC.def)如下(程序清单2):
LIBRARY libABC

EXPORTS
    ABCInit
    ABCUninit
    ABCAddValues
    ...
windows的vs系列开发工具提供了这个命令行dumpbin,它的调用方式是打开cmd,然后输入下面的命令:
dumpbin /EXPORTS libABC.dll > libABC.def

上面的命令执行后生成的libABC.def文件包含了对于生成LIB无用的信息,我们必须手工处理掉,然后才能带入下面的命令中生成LIB。假设我们已经把libABC.def处理成(程序清单2)的样子。接下来使用另外一个命令行工具,通过这个def文件生成LIB:

lib /def:libABC.def /machine:i386 /out:libABC.dll

总结下来,整个过程有3步:
1)DLL->def
2)处理def
3)使用处理后的def->LIB

整个过程在第2步不是自动化的,我曾经写过一个脚本完成第2步的自动化。后来发现MinGW提供了这样的工具:pexports。默认的MinGW没有安装pexports,你需要运行下面的命令在MinGW中安装:

$ mingw-get install pexports
于是,产生处理好的def的工作就变得非常简单:
$ pexports libABC.dll > libABC.def
无论是dumpbin还是lib这2个命令都需要VS的运行环境。因此必须先设置环境变量,通过运行一个在%VS??COMNTOOLS%的路径下的批处理文件vsvars32.bat(??表示版本号,可以查看windows环境变量得到这个信息),来完成VS环境变量设置。过程就是打开windows cmd,输入下面的命令:
%VS100COMNTOOLS%vsvars32.bat
最后我把整个处理过程写成了python脚本,这个脚本执行起来特别简单,打开MinGW命令行,进入libABC.dll所在的目录,输入下面的命令:
$ python mklib-win32.py libABC
或者
$ python mklib-win32.py libABC.dll

最后,我把mklib-win32.py贴出来,以飨读者:

#!/usr/bin/python
# filename: mklib-win32.py
# make import x86_32 import-lib from windows win32 dll
# author: cheungmine@gmail.com
# date: 2013-5
# version: 0.1
#
# MinGW:
#   $ python build-win32.py target_dll
#   $ python build-win32.py libtiff-5.dll
#   $ python build-win32.py libtiff-5
#   $ python build-win32.py tiff-5
#   $ python build-win32.py c:/path/to/libtiff-5
# ERROR: $ python build-win32.py c:\path\to\libtiff-5
#
# file operation:
# import shutil
#
## copy file:
#   shutil.copy(myfile, tmpfile)
#
## copy time of file:
#   shutil.copy2(myfile, tmpfile)
#
## copy file dir tree, the 3rd parameter means:
##   True: symbol link
##   False: use phyical copy
#   shutil.copytree(root_of_tree, destination_dir, True)
###############################################################################

import os
import platform
import time
import getopt
import optparse
import sys
import string

###############################################################################
# get installed VS???COMNTOOLS environment:
###############################################################################
def get_vspath():
  _vspath = os.getenv('VS110COMNTOOLS')
  if not _vspath:
    _vspath = os.getenv('VS100COMNTOOLS')
    if not _vspath:
      _vspath = os.getenv('VS90COMNTOOLS')
      if not _vspath:
        _vspath = os.getenv('VS80COMNTOOLS')
        if not _vspath:
          print "VS??COMNTOOLS not found"
          sys.exit()
        else:
          print "VS80COMNTOOLS =", _vspath
      else:
        print "VS90COMNTOOLS =", _vspath
    else:
      print "VS100COMNTOOLS =", _vspath
  else:
    print "VS110COMNTOOLS =", _vspath
  return _vspath

###############################################################################
# step (1): create a windows module definition: target_lib.def
#   MSCMD:
#     > dumpbin /EXPORTS target_lib.dll > ~target_lib.def
#   or MinGW:
#     $ pexports target_lib.dll > target_lib.def
# step (2): use this target_lib.def to create module import file: target_lib.lib
#   MSCMD:
#     > lib /def:target_lib.def /machine:i386 /out:target_lib.lib
###############################################################################
def make_lib(workdir, tgtname):
  print "[2-1] create a windows module definition: lib%s.def" % tgtname
  dump_def = 'cd "%s"&pexports lib%s.dll > lib%s.def' % \
    (work_dir, tgtname, tgtname)
  ret = os.system(dump_def)
  if ret == 0:
    print "[2-2] use (lib%s.def) to create import module: lib%s.lib" % (tgtname, tgtname)
    lib_cmd = 'cd "%s"&lib /def:lib%s.def /machine:i386 /out:lib%s.lib' % (workdir, tgtname, tgtname)
    cmds = 'cd "%s"&vsvars32.bat&%s&cd "%s"' % (vs_path, lib_cmd, cwd_path)
    ret = os.system(cmds)
    if ret == 0:
      print "INFO: mklib (%s/lib%s.lib) success." % (cwd_path, tgtname)
      return 0;
    else:
      print "ERROR: mklib (%s/lib%s.lib) failed." % (cwd_path, tgtname)
      return (-2)
  else:
    print "ERROR: mklib (%s/lib%s.def) failed." % (cwd_path, tgtname)
    return (-1);

###############################################################################
# current directory:
cwd_path = os.getcwd()
vs_path = get_vspath()

work_dir = "./"

# lib name == parent folder name
target_dll = "ERROR_dll_not_found"

if sys.argv.__len__() == 1:
  work_dir, target_dll = os.path.split(cwd_path)
elif sys.argv.__len__() == 2:
  work_dir = os.path.dirname(sys.argv[1])
  target_dll = os.path.basename(sys.argv[1])
else:
  print "ERROR: invalid argument"
  sys.exit(-1)

if target_dll[0:3] == "lib":
  target_dll = target_dll[3:]
tgtname, extname = os.path.splitext(target_dll)

if extname != ".dll":
  tgtname = target_dll

if work_dir == "":
  work_dir = cwd_path

print "working directory:", work_dir
print "======== make import (lib%s.lib) from (lib%s.dll) ========" % \
  (tgtname, tgtname)

make_lib(work_dir, tgtname)

sys.exit(0)

由于近期开发windows x64程序,因此需要生成64位的DLL对应的LIB,于是我又在mklib-win32.py的基础上完成了mklib-win64.py的脚本,具体原理我就不说了,读者注意脚本之中的细微之处不难理解:

#!/usr/bin/python
# filename: mklib-win64.py
# make import x86_64 import-lib from windows x64 dll
# author: cheungmine@gmail.com
# date: 2013-5
# version: 0.1
#
# MinGW:
#   $ python build-win64.py target_dll
#   $ python build-win64.py libtiff-5.dll
#   $ python build-win64.py libtiff-5
#   $ python build-win64.py tiff-5
#   $ python build-win64.py c:/path/to/libtiff-5
# ERROR: $ python build-win64.py c:\path\to\libtiff-5
#
# file operation:
# import shutil
#
## copy file:
#   shutil.copy(myfile, tmpfile)
#
## copy time of file:
#   shutil.copy2(myfile, tmpfile)
#
## copy file dir tree, the 3rd parameter means:
##   True: symbol link
##   False: use phyical copy
#   shutil.copytree(root_of_tree, destination_dir, True)
###############################################################################

import os
import platform
import time
import getopt
import optparse
import sys
import string

###############################################################################
# get installed VS???COMNTOOLS environment:
###############################################################################
def get_vspath():
  _vspath = os.getenv('VS110COMNTOOLS')
  if not _vspath:
    _vspath = os.getenv('VS100COMNTOOLS')
    if not _vspath:
      _vspath = os.getenv('VS90COMNTOOLS')
      if not _vspath:
        _vspath = os.getenv('VS80COMNTOOLS')
        if not _vspath:
          print "VS??COMNTOOLS not found"
          sys.exit()
        else:
          print "VS80COMNTOOLS =", _vspath
      else:
        print "VS90COMNTOOLS =", _vspath
    else:
      print "VS100COMNTOOLS =", _vspath
  else:
    print "VS110COMNTOOLS =", _vspath
  return _vspath

###############################################################################
# step (1): create a windows module definition: target_lib.def
#   MSCMD:
#     > dumpbin /EXPORTS target_lib.dll > ~target_lib.def
#   or MinGW:
#     $ pexports target_lib.dll > target_lib.def
# step (2): use this target_lib.def to create module import file: target_lib.lib
#   MSCMD:
#     > lib /def:target_lib.def /machine:amd64 /out:target_lib.lib
###############################################################################
def make_lib(workdir, tgtname):
  print "[2-1] create a windows module definition: lib%s.def" % tgtname
  dump_def = 'cd "%s"&pexports lib%s.dll > lib%s.def' % \
    (work_dir, tgtname, tgtname)
  ret = os.system(dump_def)
  if ret == 0:
    print "[2-2] use (lib%s.def) to create import module: lib%s.lib" % (tgtname, tgtname)
    lib_cmd = 'cd "%s"&lib /def:lib%s.def /machine:amd64 /out:lib%s.lib' % (workdir, tgtname, tgtname)
    cmds = 'cd "%s"&vcvarsall.bat x86_amd64&%s&cd "%s"' % (vs_path, lib_cmd, cwd_path)
    ret = os.system(cmds)
    if ret == 0:
      print "INFO: mklib (%s/lib%s.lib) success." % (cwd_path, tgtname)
      return 0;
    else:
      print "ERROR: mklib (%s/lib%s.lib) failed." % (cwd_path, tgtname)
      return (-2)
  else:
    print "ERROR: mklib (%s/lib%s.def) failed." % (cwd_path, tgtname)
    return (-1);

###############################################################################
# current directory:
cwd_path = os.getcwd()
vs_path = get_vspath() + "..\\..\\VC\\"
work_dir = "./"

# lib name == parent folder name
target_dll = "ERROR_dll_not_found"

if sys.argv.__len__() == 1:
  work_dir, target_dll = os.path.split(cwd_path)
elif sys.argv.__len__() == 2:
  work_dir = os.path.dirname(sys.argv[1])
  target_dll = os.path.basename(sys.argv[1])
else:
  print "ERROR: invalid argument"
  sys.exit(-1)

if target_dll[0:3] == "lib":
  target_dll = target_dll[3:]
tgtname, extname = os.path.splitext(target_dll)

if extname != ".dll":
  tgtname = target_dll

if work_dir == "":
  work_dir = cwd_path

print "working directory:", work_dir
print "======== make import (lib%s.lib) from (lib%s.dll) ========" % \
  (tgtname, tgtname)

make_lib(work_dir, tgtname)

sys.exit(0)

我做了个试验,就是用MinGW构建sqlite3,默认没有构建出我需要的dll,于是我首先进入sqlite3.o所在的目录,运行下面的命令手工构建出dll:

$ gcc -shared -fPIC sqlite3.o -o libsqlite3.dll -s
然后用mklib-win64.py生成lib文件:

$ python mklib-win64.py libsqlite3.dll
最后生成了64位版本的libsqlite3.lib,通过VS2010编写的程序测试,完全正确。

#include "C:/DEVPACK/MinGW/local64/dst/sqlite3/include/sqlite3.h"
# pragma comment(lib, "C:/DEVPACK/MinGW/local64/dst/sqlite3/lib/libsqlite3.lib");

......

void test_sqlite3()
{
  int ret;
  sqlite3       *dbconn;
  sqlite3_stmt  *stmt;
  char          *errmsg;

  ret = sqlite3_open_v2("C:/workspace/antelope/test.db", &dbconn,
    SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX |
    SQLITE_OPEN_SHAREDCACHE, 0);

  if (ret != SQLITE_OK) {
    fprintf(stdout, "ERROR: sqlite3_open_v2() error (%d).\n",
      ret);
  }
}

于是,便有了此文!


分享到:
评论

相关推荐

    通过DLL生成LIB

    最近遇到需要修改LIB名称的事,想着重新编译LIB需要编译大半天实在太耗时间了,所以自己写了个软件,只需要将DLL改个名字重新生成LIB即可,已通过测试,仅支持支持VS C/C++平台的动态链接库,自动识别X86还是X64平台...

    DLL导出生成lib文件

    对于没有lib文件的DLL,在VC中需要引用,怎么操作呢。这个工具就是实现该功能的,附带一个命令使用例子。

    由DLL文件生成LIB文件的工具

    选择DLL文件,自动生成DEF文件和LIB文件

    BCB由DLL生成LIB及def文件方法

    BCB由DLL生成LIB及def文件方法,而非转换VC的lib文件,这样生成的lib文件包含DLL中函数最全,

    生成DLL和lib文件测试案例

    VS2015生成dll文件和lib文件,里面含有测试生成的lib文件和dll文件。具体怎么配置,请参考案例

    Dll和Lib生成及使用

    DLL和Lib生成和使用,Dll和Lib同时生成的两种方法,及使用

    VS2017生成SQLITE3的DLL和LIB文件的详细说明

    介绍用最新版VS2017生成SQLITE3的DLL和LIB文件的详细说明及注意点。

    DLL2LIB.zip

    DLL生成LIB的工具箱。里面包含两个工具,一个工具快速生成DEF和LIB文件,另一个工具修改LIB文件的函数命名方式。

    dll2lib.rar (需要安装 python2.X )

    该python脚本对一个 A.dll 文件会生成如下三个文件: A.lib A.def A.exp 因为是 python 写的,所以需要下载 python (目前为 2.7 ,不要使用 3.X 版的,因为 3.X 版认为 print "string" 是语法错误的) ----------...

    MingW VC 之.a .lib .dll .def 关系

    第二种情况需要先生成lib文件再调用。 我们感兴趣的是第二种情况。具体操作实战如下: 我们只有一个mylib.dll, 需要调用一个输出函数printhello 1. 制作def dumpbin mylib.dll /exports &gt;mylib.def 得到一份完整的...

    Lib 文件生成器 (DLL2Lib)

    VC++ 和 C++Builder 的链接器在链接 DLL 时需要导入库(Import Library),在有些情况下,只能得到 DLL 文件,而没有导入库文件(比如用 Delphi 开发的 DLL),使用这个工具可以方便的生成 DLL 对应的导入库和模块定义...

    C# DLL影子生成程序,DLL转LIB

    自动生成DLL影子VC2008代码,直接编译通过, 能截取DLL调用参数, 可同时生对应LIB文件,方便调用

    DLL转Lib.zip

    可视化DLL生成Lib,再也不用操作大黑屏. 摆脱烦恼操作........ 可视化DLL生成Lib,再也不用操作大黑屏. 摆脱烦恼操作........

    Dll2Lib.exe

    VC++ 和 C++Builder 的链接器在链接 DLL 时需要导入库(Import Library),在有些情况下,只能...如用 Delphi 开发的 DLL),使用这个工具可以方便的生成 DLL 对应的 导入库和模块定义文件DEF(module-definition file)。

    pexports0.44(dll导出lib工具)

    从dll中导出lib的工具。可用于win7 64位系统。 命令格式如下:pexports XX.dll &gt; XX.def

    Vc6.0中使用DLL和LIB举例

    根据网上的资料整理的,如何在vc6下生成dll,如何使用dll,如何生成lib,如何使用lib。

    多个lib生成dll

    该工程运行在vs2010下,test为测试程序,testLib1生成第一个lib,testLib2为第二个lib,libtest2为将上述两个lib合成一个dll(测试时,需将dll放到exe文件同路劲下,或者配置环境变量)

    X264 .dll .lib .h 依据 2012-9-27日源文件编译生成的库

    依据 2012-9-27日源文件编译生成的库文件,包含所需的.h ,.lib,.dll和x264.exe文件

    sqlite在VC6下面的DLL与LIB文件

    sqlite3在vc6下面使用的dll与lib文件,已经完全验证过,请放心使用

    lib_mysqludf_sys 的win版本dll库

    lib_mysqludf_sys 的win版本dll库

Global site tag (gtag.js) - Google Analytics