從DLL產生LIB

來源:互聯網
上載者:User
從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 libABCEXPORTS    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 osimport platformimport timeimport getoptimport optparseimport sysimport 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 nametarget_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_dllif work_dir == "":  work_dir = cwd_pathprint "working directory:", work_dirprint "======== 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 osimport platformimport timeimport getoptimport optparseimport sysimport 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 nametarget_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_dllif work_dir == "":  work_dir = cwd_pathprint "working directory:", work_dirprint "======== 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);  }}

 

於是,便有了此文!

 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.