------
兄弟,我是说使用效果在没区别。一个函数,如果你确定要把它导出,就直接用__declspec(dllexport)声明得了,为何还要多此一举地自定义一个预处理器。我说的第一种做法有问题吗?我感觉在使用上完全没有问题。
=========================
有用处的,对于DLL的编写来说,函数当然当然是要导出的,但是,对于引用这个DLL的工程来说,他要用一个头文件来声明DLL中的函数的,此时,由于函数在DLL中,这个函数就要声明为导入了.用预处理器的好处就是对于DLL和引用DLL的工程,我们可以用同一个头文件,只要改一下就行了.
当然,对于一些小的工程,或是你自己做DLL,你当然可以自己手工写头文件,但是对于DLL中函数比较多的,手工再写一个头文件是很麻烦的,如果你的DLL要提供给别人用,你难道还要别人重新写一个头文件?
------
这是一种编程技巧和声明的技巧,根据不同的宏定义进行不同的定义。为何你一定觉得是没用的呢,只是你没用到有用的时候。
------
------
------
嘿嘿
虽然__declspec(dllimport)有时也可以使 exe 调用 dll 中的函数,但有时会有错误。
编译器会说什么“连接不一致”
------
好像俺在dll中导出,其他地方就声明一个原形,然后就getprocaddr了。
------
首先得承认,两种写法没有本质的区别,最终的效果是完全一样的。
另外一个问题
如果单从一个方面来说,第二种方法确实有点是“脱裤子放屁式的做法”,不过不知道楼主考虑了没有,如果不这样写,你在写DLL的时候直接写成
__declspec(dllexport) void HelloWorld();
而在你写完之后,要把这个DLL给其他人使用的时候,你再把.h中的__declspec(dllexport)改成__declspec(dllimport)吗?如果发现一次没有写好,你需要修改,那么你再把__declspec(dllimport)改成__declspec(dllexport),然后开始修改你的动态库,你写完了,再交出去的时候,你再把__declspec(dllexport)改成__declspec(dllimport)吗?如果你要改上1000次,你1000次都这样改吗?
那肯定不好,你把时间都花费到这上面,你会说,这活太低级了
------
------
保持程序的接口严谨性,避免歧义
------
你知道一般使用DLL的人要一份函数声明列表的么?
动态加载的除外
这个头文件一般是DLL作者来写的
而这个头文件在作者制作DLL内部也会用到
你作为作者的话可不想多写几分一样的代码吧?
这是出于方便考虑的,脱裤子放屁的是自己,是自己没理解其中真谛
------
------
你写dll的时候,使用的是dllexport来导出接口,
而别人使用你的dll的时候,相对的来说,是导入接口,即dllimport
使用宏的好处是,只需要一个定义,既可以在你写dll时使用,给别人头文件时也不需要修改相应的定义。
------
技巧问题,怎么用方便就怎么用。。
------
declspec是不是C语言调用标准?
不是普通都是用_stdcallPASCAL标准调用的
偶菜鸟,看不懂
------
------
------
------
------
看见你们讨论这么多了,我来吭一声吧,虽然确实如楼主所说使用起来无错,但其区别是很容易被忽略的,只需要简单的步骤验证一下即可:
假设你的A(EXE或DLL)需要调用B(DLL)中的某个导出函数:
__declspec(dllexport) void HelloWorld();
按照楼主的写法,不用宏,在项目A中直接包含这个头文件,编译、运行……OK。
打开Dependency Walker(其它合适的工具也可以),打开A(.EXE或.DLL)文件,在左边树中选择根节点,看看右边有什么内容?对了,A文件也有导出符号"HelloWorld",这是你希望看到的?
但如果使用VC默认提供的宏,这个现象不会发生。
------
------
这个东西还确实没有仔细地研究过,一直都是相当然的做法,讨论一下也有好处
不过,如果只从字面上来说,楼主的写法就不好,对于DLL来说,那当然是export,而对于使用者来说,那就是import,如果让使用者还是看到export,即使能够成功,也会产生很大疑问甚至误会的
此外,确实需要搞清楚export和import的内部作用是什么,不过,msdn上好像只是说,dllexport和dllimport是microsoft的特别关键字,其它的并没有多说。
建议楼主在微软的论坛里发贴
------
关于 __declspec(dllimport)我刚才找了一下,有人写过相关的文章,大意是说,不用这个也链接器也能工作,不过用它更好。原文是说:
不使用 __declspec(dllimport) 也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨 DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量。 你参看一下这个:
http://blog.csdn.net/Repeaterbin/archive/2009/06/15/4269666.aspx------
很久以前我出现过同样的问题,只是偶然才发现多个DLL都导出了相同的符号,经过仔细检查才发现某个头文件用了楼主的这种写法,这个头文件被多个项目引用了,造成了如此结果。不过我的项目都是DLL,你现在没有在EXE中发现导出的符号,是因为编译器在链接时找不到此符号,已经自动忽略了 __declspec(dllexport) 属性。
------
1、变量需要显示地导入。
2、如果不使用 __declspec(dllimport),那么编译生成的代码最终会类似:
call 0xXXXXXXXX
0xXXXXXXXX: jmp dword ptr __imp_function
而如果使用了dllimport,连接器会直接生成如下代码,省去中间的间接调用:
call dword ptr __imp_func
3、在网上看到如果类中用了static变量,也需要使用dllimport。
------
------
------
用extern就可以用
关键是__declspec(dllexport)更有效
楼下的详解
------
在你的dll接口文件中如下定义
C/C++ code
#ifdef _EXPORTING
#define API_DECLSPEC __declspec(dllexport)
#else
#define API_DECLSPEC __declspec(dllimport)
#endif
这样你导出的时候就定义_EXPORTING。
但是你提供这个dll给别人用的时候,你直接把这个接口文件和dll给别人就行了
人家用的时候,接口就不需要做改动,一切以提供者的为准,这样避免了一方修改后另外一方也要修改
当你在多人合作的团队中,需要维护大量的这种dll的时候作用就显现出来
------
很久以前我出现过同样的问题,只是偶然才发现多个DLL都导出了相同的符号,经过仔细检查才发现某个头文件用了楼主的这种写法,这个头文件被多个项目引用了,造成了如此结果。不过我的项目都是DLL,你现在没有在EXE中发现导出的符号,是因为编译器在链接时找不到此符号,已经自动忽略了 __declspec(dllexport) 属性。
------
------
路过看看
蒲友娱乐网------
支持,楼主好人
------
------
------
------
#40楼 小技巧:每天回帖即可获得10分可用分!
------
看来,定不定义,问题不是很大,呵呵
主要是两点:
1. 维护问题。写了好代码,以后维护的时候容易
2. 效率上会所有改善
------
楼主显然没有参与过开发过大型项目的经历。等你有了这种经历的时候,你才会发现,啊,原来用宏是这么的重要
------
路过 学习了
------
楼主的想法并没有错,不用宏一样可以完成功能,但是你的思维仅仅局限限在一个一个单一的小工程中,当你把多个工程组织到一个解决方案中,这些工程有些是动态库,当某个工程要调用另外一个动态库工程中的导出函数或类的时候,这个工程必定需要那个函数或类的声明,也就是其头文件, 你是要为每个工程都编写一份头文件,还是让所有需要用到的工程 共用一个头文件呢?如果每个工程都编写一个头文件,一旦头文件要做修改,是不是就得每个都去做修改? 如果工程仅仅只有几个,你还能记住,如果工程有好几百个,你一一去修改? 如果公用一个头文件,那就必须要用到宏。楼主明白了吧?
------
楼主仔细阅读前面的10, 25,26....,讨论就知道了,我不想重复了,优点很显然!
------
------
------
------
学习了!!
------
学习 学习!
------
marck
------
------
------
------
------
------
这样做的话,那个头文件就可以直接放在调用dll的工程里使用了。。
------
------
在导出的地方,必须__declspec(dllexport),在导入的地方,两者并没有多少区别,怎么写都一样。
这个我在几年前还在广州当学徒的时候就已经试过了。
但是有两点:
换个IDE或者说编译器,不能保证还是这个样子;
完整性;
什么是完整性呢,比如为什么所有语言都有true 和 false 呢?!true不就是false了吗?
这就是语言的完整性。
------
------

学习
------
__declspec(dllimport)也许什么实际的作用都没有,这就是LZ究底的地方。
就算是什么实际的作用都没有,个人觉得它还是有作用的,一看这个声明,就知道它是个导入函数。
就好比
#define IN
#define OUT
void strcpy(OUT char * dst, IN char * src); // 这里只是举个例子
由于预处理,IN/OUT在实际编译中不起任何作用,但是在函数原型中由于指明了这样的字眼,
很容易就知道dst是出参,src是入参。
这就是这类“标记”的作用。
而实际上,也许这些标记应该叫做annotation,而且是有实际作用的,编译器能做更多的检查。
http://msdn.microsoft.com/en-us/library/aa383701(VS.85).aspx
个人一点拙见。
------
上面的URL只是给出与dllimport类似概念的东西,而完整的dllimport应该看这个:
http://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx
------
------
------
关注。。。。
------
什么脱裤子放屁啊~
你就在自己的工程里用这个DLL,当然不会有__declspec(dllimport)的情况。但是如果你的DLL是给别人用的,你只给了个头文件,当然就会执行#define API_DECLSPEC __declspec(dllimport)了,你以为别人也会给你预定义个_EXPORTING宏啊。。。
除非你的意思是说有没有__declspec(dllimport)都一样。
------
不错的帖子,关注一下
------
------
mark' mark mark
------
楼主探究真相的精神值得鼓励,但在大家说的很清楚的情况下还不虚心接受就有点固执了。
------
为了重用
------
mark.......
------
看看Windows核心编程
------
------
关键是什么?参看《编译原理》和 PE文件格式
------
------
------
还是有用的。。。更便于修改和维护、扩展。。。
------
------
------
------
------
------
写了一篇博客,有兴趣的朋友可以看看:
总结一下__declspec(dllimport)的作用------
------
------
------
------
主要作用是你可以导入/导出用同一个符号来表示
------
__declspec(dllexport) 你可以不加试试效果啊~~特别是P/Invoke的方式里面就知道有用了
------
------
------
mark
------
學習了
------
也正为此迷惑呢,学习了
------
请教下,问个与dllimport无关的话题
前面在讨论dllimport时,提到了预编译问题,并举了如下例子
#ifdef _EXPORTING
#define API_DECLSPEC __declspec(dllexport)
#else
#define API_DECLSPEC __declspec(dllimport)
#endif
我想问的是这个_EXPORTING宏为什么要在vc的“预编译”选项里定义,而不是在头文件里定义?
谢谢
------
------
桂ICP备07017180号