VS编译动态库的时候没有生成对应的lib文件

来源:互联网 发布:龙霸点歌机网络加歌 编辑:程序博客网 时间:2024/05/01 15:56

             由于windows在动态链接的时候,必须从dll文件对应的lib文件里面寻找可链接程序的标志符,因此当你编译生成一个动态库的时候,必须生成相应的lib文件。

             有两种方法,一种是

1、在命令行执行:
dumpbin   /exports   yourdll.dll   >   yourdll.def

2、编辑   yourdll.def   文件,使之格式与.def文件格式一致。比如:

EXPORTS;
              fn1;
              fn2;

3、在命令行执行:

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

    下面是sqlite3的def文件,其实就是你要导出的函数的名字。

EXPORTSsqlite3_aggregate_contextsqlite3_aggregate_countsqlite3_auto_extensionsqlite3_backup_finishsqlite3_backup_initsqlite3_backup_pagecountsqlite3_backup_remainingsqlite3_backup_stepsqlite3_bind_blobsqlite3_bind_doublesqlite3_bind_intsqlite3_bind_int64sqlite3_bind_nullsqlite3_bind_parameter_countsqlite3_bind_parameter_indexsqlite3_bind_parameter_namesqlite3_bind_textsqlite3_bind_text16sqlite3_bind_valuesqlite3_bind_zeroblobsqlite3_blob_bytessqlite3_blob_closesqlite3_blob_opensqlite3_blob_readsqlite3_blob_reopensqlite3_blob_writesqlite3_busy_handlersqlite3_busy_timeoutsqlite3_changessqlite3_clear_bindingssqlite3_closesqlite3_collation_neededsqlite3_collation_needed16sqlite3_column_blobsqlite3_column_bytessqlite3_column_bytes16sqlite3_column_countsqlite3_column_database_namesqlite3_column_database_name16sqlite3_column_decltypesqlite3_column_decltype16sqlite3_column_doublesqlite3_column_intsqlite3_column_int64sqlite3_column_namesqlite3_column_name16sqlite3_column_origin_namesqlite3_column_origin_name16sqlite3_column_table_namesqlite3_column_table_name16sqlite3_column_textsqlite3_column_text16sqlite3_column_typesqlite3_column_valuesqlite3_commit_hooksqlite3_compileoption_getsqlite3_compileoption_usedsqlite3_completesqlite3_complete16sqlite3_configsqlite3_context_db_handlesqlite3_create_collationsqlite3_create_collation16sqlite3_create_collation_v2sqlite3_create_functionsqlite3_create_function16sqlite3_create_function_v2sqlite3_create_modulesqlite3_create_module_v2sqlite3_data_countsqlite3_db_configsqlite3_db_handlesqlite3_db_mutexsqlite3_db_statussqlite3_declare_vtabsqlite3_enable_load_extensionsqlite3_enable_shared_cachesqlite3_errcodesqlite3_errmsgsqlite3_errmsg16sqlite3_execsqlite3_expiredsqlite3_extended_errcodesqlite3_extended_result_codessqlite3_file_controlsqlite3_finalizesqlite3_freesqlite3_free_tablesqlite3_get_autocommitsqlite3_get_auxdatasqlite3_get_tablesqlite3_global_recoversqlite3_initializesqlite3_interruptsqlite3_last_insert_rowidsqlite3_libversionsqlite3_libversion_numbersqlite3_limitsqlite3_load_extensionsqlite3_logsqlite3_mallocsqlite3_memory_alarmsqlite3_memory_highwatersqlite3_memory_usedsqlite3_mprintfsqlite3_mutex_allocsqlite3_mutex_entersqlite3_mutex_freesqlite3_mutex_leavesqlite3_mutex_trysqlite3_next_stmtsqlite3_opensqlite3_open16sqlite3_open_v2sqlite3_os_endsqlite3_os_initsqlite3_overload_functionsqlite3_preparesqlite3_prepare16sqlite3_prepare16_v2sqlite3_prepare_v2sqlite3_profilesqlite3_progress_handlersqlite3_randomnesssqlite3_reallocsqlite3_release_memorysqlite3_resetsqlite3_reset_auto_extensionsqlite3_result_blobsqlite3_result_doublesqlite3_result_errorsqlite3_result_error16sqlite3_result_error_codesqlite3_result_error_nomemsqlite3_result_error_toobigsqlite3_result_intsqlite3_result_int64sqlite3_result_nullsqlite3_result_textsqlite3_result_text16sqlite3_result_text16besqlite3_result_text16lesqlite3_result_valuesqlite3_result_zeroblobsqlite3_rollback_hooksqlite3_rtree_geometry_callbacksqlite3_set_authorizersqlite3_set_auxdatasqlite3_shutdownsqlite3_sleepsqlite3_snprintfsqlite3_soft_heap_limitsqlite3_soft_heap_limit64sqlite3_sourceidsqlite3_sqlsqlite3_statussqlite3_stepsqlite3_stmt_readonlysqlite3_stmt_statussqlite3_strnicmpsqlite3_table_column_metadatasqlite3_test_controlsqlite3_thread_cleanupsqlite3_threadsafesqlite3_total_changessqlite3_tracesqlite3_transfer_bindingssqlite3_update_hooksqlite3_uri_parametersqlite3_user_datasqlite3_value_blobsqlite3_value_bytessqlite3_value_bytes16sqlite3_value_doublesqlite3_value_intsqlite3_value_int64sqlite3_value_numeric_typesqlite3_value_textsqlite3_value_text16sqlite3_value_text16besqlite3_value_text16lesqlite3_value_typesqlite3_vfs_findsqlite3_vfs_registersqlite3_vfs_unregistersqlite3_vmprintfsqlite3_vsnprintfsqlite3_vtab_configsqlite3_vtab_on_conflictsqlite3_wal_autocheckpointsqlite3_wal_checkpointsqlite3_wal_checkpoint_v2sqlite3_wal_hooksqlite3_win32_mbcs_to_utf8sqlite3_win32_utf8_to_mbcs

   第二种就是在你要到处的函数的前面加

extern "c" void__declspec(dllexport) CallC(char* szText){
 
    std::cout << szText << std::endl;
     
}

void __declspec(dllexport) CallC(char* szText){
 
    std::cout << szText << std::endl;
     
}
 
void__declspec(dllexport) __stdcall CallStd(char* szText){
 
    std::cout << szText << std::endl;
     
}
   具体好像他们又有区别,希望知道的朋友能给解释下,我也不是很清楚了,我当时就这么用,然后我的问题搞定了,看了一些资料,也没搞得很明白,具体有一段英文的好像写的还比较明白了 一起贴下面了。

Stdcall and DLL tools of MSVC and MinGW

The __stdcall calling convention has been there for a very longtime. While older calling conventions like__pascal fell intooblivion, __stdcall became the standard calling convention of Win32API functions. Unlike__cdecl (the native calling conventionof C/C++), it is supported in C/C++, Visual Basic, Java, and other languagesalike, which makes it the first choice when building a DLL for cross-languageuse.

The internal representations of both __cdecl and __stdcallfunctions havedecorations. In MSVC (Microsoft Visual C++) and MinGW(Minimalistic GNU for Windows) GCC,__cdecl function will be prefixedan underscore, and __stdcall functions will have the beginning underscoreas well as be appended by the at-sign (@) followed by the numberof bytes in the argument list. So,double __cdecl sin(double)will be decorated as _sin, and double __stdcall sin(double)will be decorated as_sin@8.

But things are not that simple. The decorations could change when theyappear in DLLs or when they are produced by different compilers. The followingtable lists the names as are produced by MSVC, MinGW, Digital Mars C/C++Compiler (DMC), Borland C++ Compiler/C++ Builder (BCC):
 Calling ConventionInternal*MSVC DLL (w/ DEF)MSVC DLL (dllexport)DMC DLLMinGW DLLBCC DLL__stdcall_Function@nFunction_Function@n_Function@nFunction@nFunction__cdecl_FunctionFunctionFunctionFunctionFunction_Function

* For all but BCC, which has the same namingconvention for symbols in code and exported name in DLL.

What a mess (especially when you notice that, for MSVC, whether aname is exported by a DEF file or by the__declspec(dllexport) attribute affects itsnaming decoration)! And although the ending decoration clearly shows howmany bytes the called function pops up from stack before returning, it isnot necessarily the most frequently used form. E.g., the Win32 APIfunctions in the system DLLs have no decoration at all, as in the caseones uses a DEF file when exporting functions with MSVC. Many DLLsintended for multi-language usage also follow this practice and use nodecoration with__stdcall functions (although the Java NativeInterface, on Win32 platforms, will accept functions either undecoratedor decorated in the Microsoft way, the latter being the preferredform). The remaining part of this article is thus devoted to thecreation and use of such DLLs with MSVC and MinGW, as well as theintroduction and comparison of related tools (there are good articles athttp://www.bcbdev.com/articles.htmexplaining the complexities of DLLs with Borland C++ Builder, so I neednot bother to say anything more about it).

Tools working with DEF files

First, I will talk about the DEF file format and the relevant tools usedwith MSVC and MinGW. Many intricacies lie here.

DEF file format

We care about only two sections of the DEF file: the LIBRARY section andthe EXPORTS section. The LIBRARY section specifies the internal name ofthe DLL; and the EXPORTS section specifies the function or data items toexport. A short example follows:
LIBRARY    testdll.dllEXPORTS    cdeclFunction                       @1    _stdcallFunction@8                  @2    aliasName = cdeclFunction           @3
This DEF file defines three exports for a testdll.dll:the first one is a __cdecl function, the second one a __stdcallfunction, and the third one an alias of the first function (the leftside of the "=" sign is an exported name and the right side the internalname). The three functions are also assignedordinals. A functioncan be called by its name or its ordinal.

CL

CL can accept a DEF file on the command line, and it simply passesthe file name toLINK. E.g.,
cl /LD testdll.obj testdll.def
will become
link /out:testdll.dll /dll /implib:testdll.lib /def:testdll.def testdll.obj

LINK

LINK is our most important tool when treating DLL and DEF fileswith MSVC. The command line mentioned inCL already shows the optionscommonly used when creating a DLL with a DEF file. The main point is: ifwe do not use a DEF file when creating a DLL, the exported name of a__stdcallfunction will be _Function@n; but if we use a DEFfile, the exported name could be eitherFunction or _Function@n;if both names appear, only the undecorated form is used. However, wecan force both forms of exports with the following lines in the EXPORTSsection:
TestFunction = _TestFunction@4_TestFunction@4 = _TestFunction@4

LIB

If we have the DLL from somebody else (no source available), and we havethe DEF file, the easiest way to create an import library is to use theLIBtool. The following syntax is often enough (checkMSDNfor more details):
lib /def:DEF_file
Nota bene: 1) it seems LIB does not accept aliased forms(it will simply ignore the part after the equal-sign); 2) it assumes allfunctions in the DEF file__cdecl. The second point lies in thefact that the import library it produces will map each symbol in the DLLto an internal name with an underscore prefixed, i.e., the linker usingthe import library will try to resolve an undefined symbol_Functionto the symbol Function in the DLL. It takes no special care ofthe__stdcall calling convention. With some techniques we coulduse LIB to produce import libraries for __stdcall functions,but the caller could only call them by ordinal, not by name. The detailsare left as an exercise:-).

gcc

Here we use gcc to call ld. The reason why we do not uselddirectly is that usinggcc is generally more convenient. The -sharedoption is specially designed to produce DLLs. We could also use the-Wloption to pass special link options.

ld

GNU ld has many options regarding DLLs, but we shall only focuson four (help information follows):
--add-stdcall-alias                Export symbols with and without @nn--kill-at                          Remove @nn from exported symbols--out-implib <file>                Generate import library--output-def <file>                Generate a .DEF file for the built DLL
Either gcc or ld can accept a DEF file directly on the commandline. When a function (say,TestFunction@4) is marked as__declspec(dllexport), and we have the following line in theEXPORTS section,
TestFunction = TestFunction@4
both symbols will be exported to the DLL (LINK has similarbehaviour too). This behaviour is different fromdllwrap, whichwe shall talk of immediately.

dllwrap

GNU dllwrap could produce a DLL by a DEF file. We generally usedllwrapin the following syntax,
dllwrap --def DEF_file -o DLL_file OBJ_files [--output-lib LIB_file]
and dllwrap will transparently call gcc, ld, and dlltoolto fulfil its task. If dllwrap is asked to produce an import library(--output-lib), it will letdlltool do it.Unlike LINK or ld,dllwrap will ignore theexport specifications in an object file, and will not export aname unless it is specifically listed as an exported name in the EXPORTSsection (unless one does not use a DEF file at all).

dlltool

GNU dlltool may be used to create the files needed to build anduse dynamic link libraries (DLLs). The following options are of interestto us currently:
-l --output-lib <outname> Generate an interface library.-D --dllname <name>       Name of input dll to put into interface lib.-d --input-def <deffile>  Name of .def file to be read in.-U --add-underscore       Add underscores to symbols in interface library.-k --kill-at              Kill @<n> from exported names.
dlltool works like LIB, and similarly it willignore the part after the equal-sign in a DEF file, but ithas its special features that somehow compensate for this shortcoming:
  • the -U optionmakes the items in the DEF file map to symbols prefixed with anunderscore in the DLL, and
  • the -k option makes theitems in the DEF file map to symbols stripped of@n inthe DLL.

pexports

This is a stand-alone open-source tool to produce a DEF file from a givenDLL. It is not distributed with MSVC or MinGW, and you may choose to downloadhereif you do not find it elsewhere.

The __stdcall DLL and the import library

Having learnt so much about the tools, now we are ready to do what we wanted.We still needsed (search on the Internet if you do not alreadyhave this useful tool), and a knowledge of regular expression is requiredto understand thoroughly how it works.

Microsoft Visual C++

The simplest way to produce a DLL is to use the /LD command-lineoption ofCL:
cl /LD OBJ_files
The resulting DLL will have exported names like _MyFunction@8,as is shown in the `MSVC DLL (dllexport)' columnabove. To create symbols with no decoration, we must use a DEF file. Thefollowing is an automatic way to create a DEF file from the DLL if__declspec(dllexport) is used to indicate which functions toexport:
link /out:DLL_file /dll OBJ_filespexports DLL_file | sed "s/^_\([[:alnum:]_]\+\)@[[:digit:]]\+/\1/" > DEF_file
At this step, you may also want to generate a DEF file to make the DLLusable with MinGW source.
pexports DLL_file | sed "s/^_\([[:alnum:]_]\+\)\(@[[:digit:]]\+\)/\1\2/" > DEF_for_gcc
Once you have the object files and the DEF file, creating the DLL and theimport library can be done in one step:
link /out:DLL_file /dll /def:DEF_file /implib:LIB_file OBJ_files
And you are free to use the DLL and the import library now as you wish.

MinGW GCC

If we do not need to control which functions to export except by __declspec(dllexport),we can type:
gcc -shared -o DLL_file OBJ_files -Wl,--output-def,DEF_filegcc -shared -o DLL_file OBJ_files -Wl,--kill-atdlltool -d DEF_file --dllname DLL_file --output-lib LIB_file --kill-at
If we want to use a DEF file to control which functions to export, we canstart by (assuming__declspec(dllexport) is used to indicate whichfunctions to export)
gcc -shared -o DLL_file OBJ_files -Wl,--kill-at,--output-def,DEF_file
to produce a DEF file with exports like "Function =Function@n@Ordinal". After editing it to our will, the following commandswill finish the job:
dllwrap --def DEF_file -o DLL_file OBJ_filessed "s/[[:alnum:]_]\+ *= *//" DEF_file > New_DEF_filedlltool -d New_DEF_file --dllname DLL_file --output-lib LIB_file --kill-at
And the import library is now at your hand to use.
 

I am not sure whether I have stated clearly, but I have listed all myfindings when I struggled to find out how to use the DLL tools properlyand how to deal with__stdcall functions in DLLs. Hope you findit useful.

ACKNOWLEDGEMENT: The MinGW mailing list provided much usefulinformation; Luke Dunstan provided important suggestions and corrections.




原创粉丝点击