模块接口解惑

软件工程最依托的就是模块接口,所以,早研究为好

window不像linux的gcc编译器,默认把类库中所有函数都开放的。
可以说它更严格。当然gcc也是可以通过
__attribute__((visibility(“default”)))定义成宏开关的方式来放出个别函数和隐藏hidden。
暂且不表,只说:
__declspec(dllimport)——代号A
__declspec(dllexport)——代号B
B的作用是,想导出类和函数,必须用B声明,这样后台就会把要导出东东的声明无声的加入到.obj和编好的dll中。这时.def可有可无了。当然,你不想用B,那就带着.def给别人用吧。

A用的场景本人总结现在有二:
一,前提你是甲方时,即当你的app或者dll要调用别人的类或函数时,修饰用A,告诉编译器,这函数铁定去外面的dll找吧,当然需要外部dll声明了B,与你呼应了。
__declspec(dllexport) void __cdecl Function1(void);
class __declspec(dllexport) MyClass{/*类的定义*/};//
二,前提你是乙方时,当你的的导出类中有静态变量时,需要带着B的修饰,如:
#ifdef SIMPLEDLL_EXPORT
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
其实还有第三点,就是你为乙方的甲方,会用到丙方,那么带上B的修饰,不会让你头很大。

在讲上面概念时,我没有提显示和隐式链接。防止混淆。当你修饰了接口,那么编译器就知晓了呼应关系,那么自然用隐式链接了。但这不是唯一途径,比如:应用lib和VS配置(程序内声明有同样效果#pragma comment(lib,”XXX.lib”))。

而显示链接时,下面有两平台的代码参考。此时,用不着A,B的修饰了。
//windows
SyncCmd SyncExecute = (SyncCmd)GetProcAddress(hModule, “SyncExecute”);
//linux(使用so非a时)
SyncCmd SyncExecute = (SyncCmd )dlsym(hModule, “SyncExecute”);

另外,提一句,还一个维度在接口声明处,那就是
extern “C”——–模块之间的连接约定———位置在顶头
__cdecl————调用约定关键字——–返回值类型和函数名称之间