- 上一节讲到了声明,这一节开始讲入口函数和导出函数,先上入口函数代码
BOOL APIENTRY DllMain( HMODULE 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:
break;
}
return TRUE;
}
-
BOOL APIENTRY DllMain
这是程序自动生成的入口函数,APIENTRY
是一个宏定义WINAPI
, 而WINAPI又是另一个宏定义名为__stdcall
, -
stdcall
直译是标准呼叫,参数从右至左的顺序压参数入栈,由被调用函数把参数弹出栈,
-BOOL
是这个入口函数的返回值,是个布尔值,里面也就是0和1,返回0一般表示失败,返回1表示成功. -
HMODULE hModule
,是所传的第一个参数,是指向DLL本身的实例句柄,这里非常重要的就是指向的是本DLL,而不主调用程序的句柄,这个句柄在使用MFC等弹窗的时候非常有用,这里暂时还用不上,只要知道就好了.因为MFC调用窗口资源的时候是需要本DLL的窗口句柄的,而MFC本身是自带了DLLMAIN入口函数的,所以不能重复调用会造成编译失败,所以当使用纯C++的时候这个参数就非常重要了,当然这里暂时也用不上 -
第二个参数
DWORD ul_reason_for_call
,是指明了DLL被调用的原因,后面的switch (ul_reason_for_call)就是在不同的调用周期可以安插进不同的代码 -
可以看到后面有四个原因,先后分别是进程创建,线程调用,线程释放,进程释放
-
第③lpReserved参数:保留,目前没什么意义。
-
下面暴露导出函数
extern "C" _declspec(dllexport) int WoDeDll(VGCore::IVGApplication * corel, HWND Wnd) {
corelApp = corel; //给IVGApplication赋值
hAppWnd = Wnd; //给窗口句柄赋值
Qunzu(); //调用群组功能, 因为在函数内部调用其它函数的时候, 这个被调用的函数必须在本函数之前有函数本体或声明,
//两者只要有其一都行,所以为了避免出现问题,一般这种主调用函数放在最后面就行了.
return 1; //全部调用完毕,返回整数1.
}
-
extern "C"
是说这个函数是以C语言风格编译的,在我们这个程序中是必带的,如果不带,编译器就会使用C++风格,会导致VBA调用失败.所以我们可以看到C语言虽然很古老,但是很多其它语言对它的兼容性还是非常友好的 -
_declspec()
这个是用来告诉编译器有关这个函数的事,里面传的dllexport
就是一个DLL导出修饰,用来暴露dll中的变量或方法.关于是使用dllexport还是dllimport还是有些玄学搞不太清,两种方法都是把函数暴露加载出来,反正用dllexport就完事了. -
int
就是返回值是设置的一个整数,WoDeDll
是函数名,到时候VBA里面是需要用到这个名字来定位这个函数的,否则无法调用. -
第一个参数
VGCore::IVGApplication * corel
,可以看到是结构体IVGApplication
的指针,也就是告诉了本函数,到时候主调函数传的第一个参数,是一个指向IVGApplication结构体的地址指针,所以程序就是这样定位到了主调程序的IVGApplication结构体在内存中的起始位置,一般来说指针都是指向的起始位置,然后根据结构体的字节长度,就能访问到该结构体的任意变量.因为这个结构体就是在VGCoreAuto.tlh里面定义的,所以程序对这个结构的长度和各个字节是什么类型全部都是了解的. -
第二个参数是
HWND Wnd
,一个窗口句柄值,可要可不要,我是为了方便顺便传了进来.VBA调用中就把主窗口的句柄传进来方便模态弹窗. -
我们在函数内部第一行,在第一时间对
corelApp
进行赋值, 因为被传的参数只能在函数内部使用, 而外部的函数要使用就要借用全局变量或者函数传参,因为这个涉及到了变量的访问的问题,在文件开头声明的变量是全局的,是所有本文件内部的函数都可以访问的, -
所以为了让这个变量在本页程序中通用,就必须在事先声明全局变量,然后再在第一时间初始化赋值,所以这里的第一行代码就是给这个IVGApplication结构体指针赋值.
-
我们调用的功能就放在另一个函数
Qunzu()
中,所以下一节就要展开Qunzu()讲群组的具体代码了, -
因为被主调函数所调用的量必须在前面有声明或者实现,所以后面一节的Qunzu要写在导出函数前面,