我用vs.net 2003做了一个静态库,生成了test.lib,拿到别外一个程序引用时出现了test.dll找不到,我原想把代码做在lib内,可能实际没有生成,请问,编译的时候怎么设,别外在BCB用到的话,需要注意那里.

解决方案 »

  1.   

    setting additional lib path to include test.lib
    add test.h to your project
      

  2.   

    那就不是静态库吧~
    vc.net没用过~
    vc6有静态库这一项~
      

  3.   

    我现在行了,原来做静态库不用def文件就行,做了是不包括代码,不做是有代码的,大家来讨论,到时给分
      

  4.   

    引用时出现了test.dll找不到    //看起来应该是动态库, 不是静态的//静态的只要link *.lib就可以了, include *.h另外静态库可以在BCB下用吗, 不懂, dll肯定可以
      

  5.   

    没看懂.......
    是这样的,静态库有两种类型,一种是包含具体代码的,引用就可以编译到程序里面,另一种是DLL的接口库,没有代码
      

  6.   

    动态链接库的创建  在Visual C++6.0开发环境下,打开FileNewProject选项,可以选择Win32 Dynamic-Link Library或MFC AppWizard[dll]来以不同的方式来创建Non-MFC Dll、Regular Dll、Extension Dll等不同种类的动态链接库。  1. Win32 Dynamic-Link Library方式创建Non-MFC DLL动态链接库  每一个DLL必须有一个入口点,这就象我们用C编写的应用程序一样,必须有一个WINMAIN函数一样。在Non-MFC DLL中DllMain是一个缺省的入口函数,你不需要编写自己的DLL入口函数,用这个缺省的入口函数就能使动态链接库被调用时得到正确的初始化。如果应用程序的DLL需要分配额外的内存或资源时,或者说需要对每个进程或线程初始化和清除操作时,需要在相应的DLL工程的.CPP文件中对DllMain()函数按照下面的格式书写。
      BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
    {
    switch( ul_reason_for_call )
    {
    case DLL_PROCESS_ATTACH:
    .......
    case DLL_THREAD_ATTACH:
    .......
    case DLL_THREAD_DETACH:
    .......
    case DLL_PROCESS_DETACH:
    .......
    }
    return TRUE;
    }
       参数中,hMoudle是动态库被调用时所传递来的一个指向自己的句柄(实际上,它是指向_DGROUP段的一个选择符);ul_reason_for_call是一个说明动态库被调原因的标志,当进程或线程装入或卸载动态链接库的时候,操作系统调用入口函数,并说明动态链接库被调用的原因,它所有的可能值为:DLL_PROCESS_ATTACH: 进程被调用、DLL_THREAD_ATTACH: 线程被调用、DLL_PROCESS_DETACH: 进程被停止、DLL_THREAD_DETACH: 线程被停止;lpReserved为保留参数。到此为止,DLL的入口函数已经写了,剩下部分的实现也不难,你可以在DLL工程中加入你所想要输出的函数或变量了。  我们已经知道DLL是包含若干个函数的库文件,应用程序使用DLL中的函数之前,应该先导出这些函数,以便供给应用程序使用。要导出这些函数有两种方法,一是在定义函数时使用导出关键字_declspec(dllexport),另外一种方法是在创建DLL文件时使用模块定义文件.Def。需要读者注意的是在使用第一种方法的时候,不能使用DEF文件。下面通过两个例子来说明如何使用这两种方法创建DLL文件。  1)使用导出函数关键字_declspec(dllexport)创建MyDll.dll,该动态链接库中有两个函数,分别用来实现得到两个数的最大和最小数。在MyDll.h和MyDLL.cpp文件中分别输入如下原代码:
     //MyDLL.h
    extern "C" _declspec(dllexport) int Max(int a, int b);
    extern "C" _declspec(dllexport) int Min(int a, int b);
    //MyDll.cpp
    #include
    #include"MyDll.h"
    int Max(int a, int b)
    {
    if(a>=b)return a;
    else
    return b;
    }
    int Min(int a, int b)
    {
    if(a>=b)return b;
    else
    return a;
    }
       该动态链接库编译成功后,打开MyDll工程中的debug目录,可以看到MyDll.dll、MyDll.lib两个文件。LIB文件中包含DLL文件名和DLL文件中的函数名等,该LIB文件只是对应该DLL文件的"映像文件",与DLL文件中,LIB文件的长度要小的多,在进行隐式链接DLL时要用到它。读者可能已经注意到在MyDll.h中有关键字"extern C",它可以使其他编程语言访问你编写的DLL中的函数。  2)用.def文件创建工程MyDll  为了用.def文件创建DLL,请先删除上个例子创建的工程中的MyDll.h文件,保留MyDll.cpp并在该文件头删除#include MyDll.h语句,同时往该工程中加入一个文本文件,命名为MyDll.def,再在该文件中加入如下代码:LIBRARY MyDll
    EXPORTS
    Max
    Min  其中LIBRARY语句说明该def文件是属于相应DLL的,EXPORTS语句下列出要导出的函数名称。我们可以在.def文件中的导出函数后加@n,如Max@1,Min@2,表示要导出的函数顺序号,在进行显式连时可以用到它。该DLL编译成功后,打开工程中的Debug目录,同样也会看到MyDll.dll和MyDll.lib文件。  2.MFC AppWizard[dll]方式生成常规/扩展DLL  在MFC AppWizard[dll]下生成DLL文件又有三种方式,在创建DLL是,要根据实际情况选择创建DLL的方式。一种是常规DLL静态链接到MFC,另一种是常规DLL动态链接到MFC。两者的区别是:前者使用的是MFC的静态链接库,生成的DLL文件长度大,一般不使用这种方式,后者使用MFC的动态链接库,生成的DLL文件长度小;动态链接到MFC的规则DLL所有输出的函数应该以如下语句开始: 
     AFX_MANAGE_STATE(AfxGetStaticModuleState( )) //此语句用来正确地切换MFC模块状态
       最后一种是MFC扩展DLL,这种DLL特点是用来建立MFC的派生类,Dll只被用MFC类库所编写的应用程序所调用。前面我们已经介绍过,Extension DLLs 和Regular DLLs不一样,它没有一个从CWinApp继承而来的类的对象,编译器默认了一个DLL入口函数DLLMain()作为对DLL的初始化,你可以在此函数中实现初始化,代码如下:
     BOOL WINAPI APIENTRY DLLMain(HINSTANCE hinstDll,DWORD reason ,LPVOID flmpload)
    {
    switch(reason)
    {
    ……………//初始化代码;
    }
    return true;
    }
       参数hinstDll存放DLL的句柄,参数reason指明调用函数的原因,lpReserved是一个被系统所保留的参数。对于隐式链接是一个非零值,对于显式链接值是零。  在MFC下建立DLL文件,会自动生成def文件框架,其它与建立传统的Non-MFC DLL没有什么区别,只要在相应的头文件写入关键字_declspec(dllexport)函数类型和函数名等,或在生成的def文件中EXPORTS下输入函数名就可以了。需要注意的是在向其它开发人员分发MFC扩展DLL 时,不要忘记提供描述DLL中类的头文件以及相应的.LIB文件和DLL本身,此后开发人员就能充分利用你开发的扩展DLL了。四、动态链接库DLL的链接  应用程序使用DLL可以采用两种方式:一种是隐式链接,另一种是显式链接。在使用DLL之前首先要知道DLL中函数的结构信息。Visual C++6.0在VCin目录下提供了一个名为Dumpbin.exe的小程序,用它可以查看DLL文件中的函数结构。另外,Windows系统将遵循下面的搜索顺序来定位DLL: 1.包含EXE文件的目录,2.进程的当前工作目录, 3.Windows系统目录, 4.Windows目录,5.列在Path环境变量中的一系列目录。  1.隐式链接  隐式链接就是在程序开始执行时就将DLL文件加载到应用程序当中。实现隐式链接很容易,只要将导入函数关键字_declspec(dllimport)函数名等写到应用程序相应的头文件中就可以了。下面的例子通过隐式链接调用MyDll.dll库中的Min函数。首先生成一个项目为TestDll,在DllTest.h、DllTest.cpp文件中分别输入如下代码:
      //Dlltest.h
    #pragma comment(lib,"MyDll.lib")
    extern "C"_declspec(dllimport) int Max(int a,int b);
    extern "C"_declspec(dllimport) int Min(int a,int b);
    //TestDll.cpp
    #include
    #include"Dlltest.h"
    void main()
    {int a;
    a=min(8,10)
    printf("比较的结果为%d ",a);
    }
     
       在创建DllTest.exe文件之前,要先将MyDll.dll和MyDll.lib拷贝到当前工程所在的目录下面,也可以拷贝到windows的System目录下。如果DLL使用的是def文件,要删除TestDll.h文件中关键字extern "C"。TestDll.h文件中的关键字Progam commit是要Visual C+的编译器在link时,链接到MyDll.lib文件,当然,开发人员也可以不使用#pragma comment(lib,"MyDll.lib")语句,而直接在工程的Setting->Link页的Object/Moduls栏填入MyDll.lib既可。  2.显式链接  显式链接是应用程序在执行过程中随时可以加载DLL文件,也可以随时卸载DLL文件,这是隐式链接所无法作到的,所以显式链接具有更好的灵活性,对于解释性语言更为合适。不过实现显式链接要麻烦一些。在应用程序中用LoadLibrary或MFC提供的AfxLoadLibrary显式的将自己所做的动态链接库调进来,动态链接库的文件名即是上述两个函数的参数,此后再用GetProcAddress()获取想要引入的函数。自此,你就可以象使用如同在应用程序自定义的函数一样来调用此引入函数了。在应用程序退出之前,应该用FreeLibrary或MFC提供的AfxFreeLibrary释放动态链接库。下面是通过显式链接调用DLL中的Max函数的例子。
     #include 
    #include
    void main(void)
    {
    typedef int(*pMax)(int a,int b);
    typedef int(*pMin)(int a,int b);
    HINSTANCE hDLL;
    PMax Max
    HDLL=LoadLibrary("MyDll.dll");//加载动态链接库MyDll.dll文件;
    Max=(pMax)GetProcAddress(hDLL,"Max");
    A=Max(5,8);
    Printf("比较的结果为%d ",a);
    FreeLibrary(hDLL);//卸载MyDll.dll文件;
    }
       在上例中使用类型定义关键字typedef,定义指向和DLL中相同的函数原型指针,然后通过LoadLibray()将DLL加载到当前的应用程序中并返回当前DLL文件的句柄,然后通过GetProcAddress()函数获取导入到应用程序中的函数指针,函数调用完毕后,使用FreeLibrary()卸载DLL文件。在编译程序之前,首先要将DLL文件拷贝到工程所在的目录或Windows系统目录下。  使用显式链接应用程序编译时不需要使用相应的Lib文件。另外,使用GetProcAddress()函数时,可以利用MAKEINTRESOURCE()函数直接使用DLL中函数出现的顺序号,如将GetProcAddress(hDLL,"Min")改为GetProcAddress(hDLL, MAKEINTRESOURCE(2))(函数Min()在DLL中的顺序号是2),这样调用DLL中的函数速度很快,但是要记住函数的使用序号,否则会发生错误。
      

  7.   

    To the bro upstairs: what the master wants is for VS2003.net, not for VC6...btw, I have no idea of VS2003.net...  :)
      

  8.   

    现在以一个简单的数学函数库为例介绍静态库的创建和使用。要创建静态库,选择File->New菜单,弹出New对话框。选择Projects标签,在项目类型列表框中选择Win32 Static Library,在Name中输入mymath,表明要创建一个mymath.lib的静态库文件。然后用Project->Add to Project->Files菜单往mymath工程中加入以下两个文件:1.头文件(见清单9.1):定义了Summary和Factorial两个函数,分别用于完成求和与阶乘。注意这里使用C风格的函数,需要加入extern “C”关键字,表明它是C风格的外部函数。清单9.1 头文件#ifndef _MYMATH_H#define _MYMATH_Hextern “C”{int Summary(int n);int Factorial(int n);}#endif2.源文件:包含了Summary和Factorial函数的定义,见清单9.2。清单9.2 源文件int Summary(int n){int sum=0;int i;for(i=1;i<=n;i++){sum+=i;}return sum;}int Factorial(int n){int Fact=1;int i;for(i=1;i<=n;i++){Fact=Fact*i;}return Fact;} 在Build菜单下,选择Build菜单下的Build mymath.lib。Visual C++编译链接工程,在mymath\debug目录下生成mymath.lib文件。至此,静态连接库生成的工作就做完了。下面用一个小程序来测试这个静态库。提示:用户在交付最终静态连接库时,只需要提供.lib文件和头文件,不需要再提供库的源代码。  9.2.2测试静态库 用AppWizard生成一个基于对话框的应用程序test。打开test资源文件,修改IDD_TEST_DIALOG对话框资源,加入两个按钮。按钮ID和文字为:IDC_SUM “&Summary”IDC_FACTORIAL “&Factorial”如图9-1所示。图9-1 修改test对话框用ClassWizard为上述两个按钮Click事件生成消息处理函数OnSum和OnFactorial,并加入代码,修改后的OnSum和OnFactorial见清单9.3。清单9.3 OnSum和OnFactorial函数定义void CTestDlg::OnSum() {// TODO: Add your control notification handler code hereint nSum=Summary(10);CString sResult;sResult.Format("Sum(10)=%d",nSum);AfxMessageBox(sResult);}void CTestDlg::OnFactorial() {// TODO: Add your control notification handler code hereint nFact=Factorial(10);CString sResult;sResult.Format("10!=%d",nFact);AfxMessageBox(sResult);}由于要使用mymath.lib中的函数,首先要将mymath.lib和mymath.h两个文件拷贝到test目录下。然后用Project->Add to Project->Files命令,将mymath.lib加入到工程中。在testdlg.cpp文件头部,还要加入头文件mymath.h:#include "stdafx.h"#include "Test.h"#include "TestDlg.h" #include "mymath.h"#ifdef _DEBUG#define new DEBUG_NEW#undef THIS_FILEstatic char THIS_FILE[] = __FILE__;#endif
      

  9.   

    怎么把导出的函数映射出来,mapfile里的
      

  10.   

    我怎么测试的时候老是出错呢?
    Linking...
    TestStaticlibDlg.obj : error LNK2001: unresolved external symbol _Summary
    TestStaticlibDlg.obj : error LNK2001: unresolved external symbol _Factorial
    Debug/TestStaticlib.exe : fatal error LNK1120: 2 unresolved externals
    Error executing link.exe.