同时生成 Release版和Debug版DLL的方法

同时生成 Release版和Debug版DLL的方法

warning LNK4070的解决办法

重命名了一个MFC常规DLL的工程文件(VS C++ 2005编译环境),结果在编译时出现这样的警告:1>B.exp : warning LNK4070: .EXP 中的 /OUT:A.dll 指令与输出文件名"../outdir/Debug/B.dll"不同;忽略指令(这里假设原来的工程文件名叫A.vcproj,改名后叫B.vcproj)

后来我发现虽然输出为B.dll,但是对应的静态库B.lib被其它工程以隐式链接的方式调用时,使用的还是A.dll(这个可以使用Dependcies工具来查看),这样导致往往其它动态库不能加载成功。这下我不能把它仅仅当做warning而弃之不管了,于是上网查资料解决这个warning。查完资料,再结合自己的思考,大致明白了造成warning的原因。

原来是虽然我修改了工程名,但是没有修改这个工程的def文件中LIBRARY字段的值,造成工程的输出文件和def文件的LIBRARY字段的值不一样。比如我把A.vcproj修改为B.vcproj,但在def文件还是LIBRARY "A"。这时只需将def文件中的LIBRARY字段修改为:LIBRARY "B"。这样就能完全消除这个警告。而被别的库以隐式链接调用也是以B.dll面目出现的。

 

VC6.0程序移到VS2010出现警告之warning LNK4017:

VC 6.0的程序中看到.def文件为:

编译时总是出现警告:

\EvaDataGr.def(5): warning LNK4017: DESCRIPTION 语句不支持目标平台;已忽略

找了很久也没找到相应的解决办法,查到一篇博客中的.def文件定义后,暂用删除DESCRIPTION  'DataTypeWm Windows Dynamic Link Library'这句话的办法编译。

 

.def文件定义

DLL中导出函数的声明有两种方式:一种为在函数声明中加上__declspec(dllexport),这里不再举例说明;另外一种方式是采用模块定义(.def) 文件声明,.def文件为链接器提供了有关被链接程序的导出、属性及其他方面的信息。

首先创建一个DLL程序,.cpp

[cpp] view plain copy

int __stdcall Add(int numa, int numb)  

{  

       return (numa + numb);  

}  

  

int __stdcall Sub(int numa, int numb)  

{  

        return (numa - numb);  

}  

然后创建一个.def的文件,在里面加上

;DllTestDef.lib : 导出DLL函数

;作者:----

LIBRARY DllTestDef

EXPORTS 

Add @ 1

Sub @ 2

最后创建一个测试程序:.cpp文件如下:

[cpp] view plain copy

#include <iostream>  

#include <windows.h>  

  

using namespace std;  

  

typedef int (__stdcall *FUN)(int, int);  

HINSTANCE hInstance;  

FUN   fun;  

  

int main()  

{  

       hInstance = LoadLibrary("DLLTestDef.dll");  

       if(!hInstance)  

           cout << "Not Find this Dll" << endl;  

       fun = (FUN)GetProcAddress(hInstance, MAKEINTRESOURCE(1));  

       if (!fun)  

       {  

              cout << "not find this fun" << endl;  

       }  

       cout << fun(1, 2) << endl;  

       FreeLibrary(hInstance);  

       return 0;  

}  

说明:

.def文件的规则为:

  1. LIBRARY语句说明.def文件相应的DLL
  2. EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号将发挥其作用);
  3. .def 文件中的注释由每个注释行开始处的分号(;) 指定,且注释不能与语句共享一行。

如果导出 C++ 文件中的函数,必须将修饰名放到.def 文件中,或者通过使用外部“C”定义具有标准 C 链接的导出函数。如果需要将修饰名放到.def 文件中,则可以通过使用 DUMPBIN 工具或 /MAP 链接器选项来获取修饰名。请注意,编译器产生的修饰名是编译器特定的。如果将 Visual C++ 编译器产生的修饰名放到 .def 文件中,则链接到 DLL 的应用程序必须也是用相同版本的 Visual C++ 生成的,这样调用应用程序中的修饰名才能与 DLL .def 文件中的导出名相匹配。

如果生成扩展 DLL 并使用 .def 文件导出,则将下列代码放在包含导出类的头文件的开头和结尾:

#undef AFX_DATA#define AFX_DATA AFX_EXT_DATA// <body of your header file>#undef AFX_DATA#define AFX_DATA

这些代码行确保内部使用的 MFC 变量或添加到类的变量是从扩展 DLL 导出(或导入)的。例如,当使用 DECLARE_DYNAMIC 派生类时,该宏扩展以将 CRuntimeClass 成员变量添加到类。省去这四行代码可能会导致不能正确编译或链接 DLL,或在客户端应用程序链接到 DLL 时导致错误。

当生成 DLL 时,链接器使用 .def 文件创建导出 (.exp) 文件和导入库 (.lib) 文件。然后,链接器使用导出文件生成 DLL 文件。隐式链接到 DLL 的可执行文件在生成时链接到导入库。

请注意,MFC 本身使用 .def 文件从 MFCx0.dll 导出函数和类。

 

同时生成 Release版和Debug版DLL的方法

warning LNK4070: /OUT:dll.dll directive in .EXP ..

我在DLL项目中遇到了,因为要对Debug版和Release版分别指定不同的输出文件名。对Debug版,我指定输出文件为dllD.dll,对Release版指定为dllR.dll

解决方法有两个:

1)删掉自动生成的dll.DEF文件,在代码中使用_declspec(dllexport)导出函数;

2)删掉dll.DEF文件中LIBRARY字段后面双引号及其内部的库名即可,也可以将其改掉。如改为:

; dll.def : Declares the module parameters for the DLL.

LIBRARY      "dllD"

DESCRIPTION 'dll Windows Dynamic Link Library'

EXPORTS

    ; Explicit exports can go here

******************************************************************************************

还有更好方法:

  1. 生成两份DEF文件:xx.def //Release版本;xxD.def //Debug版本
  2. 把这两个文件都添加到项目中;
  3. 只要在Debug项目的Setting中选中xx.def,在右边的General中在Exclude file from built前打勾;同样在Release项目的Setting中选中xxD.def,在右边的General中在Exclude file from built前打勾;
  4. 接下来就Betch Build
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值