此中只有实际才操作,而无相关理论
⊃2; DLL的创建
首先,用VC集成开发界面中的“新建”,新建一个项目。无论是VC6.0还是VC.NET,都有建立DLL项目的选项。只不过有些稍有不同,例如VC.NET中就有ISAPI DLL,扩展存储过程DLL等,这些都不在讨论的范围。例如我们建立了一个用静态连接MFC库的DLL项目,名称为mydll
然后,编辑mydll.cpp文件,在其中加入我们自己的函数void go()。注意,不需要在mydll.h中声明它,而需要将函数头变成如下样子:
extern “c” __declspec(dllexport) void go()
{
//code……
}
dllexport表示这个函数是由外部调用的。
由于是否带参数,要影响到外部调用的方式,因此,我们再声明一个带参数的函数:
extern “c” __declspec(dllexport) void went(CString str)
{
//code……
}
OK,下面编译连接形成mydll.dll文件。
⊃2; DLL的调用
好,下面我们就用VC写个程序调用它。在调用的函数中,首先要获得DLL的句柄,有如下语句:
HINSTANCE dllinstance;
dllinstance=::LoadLibrary(strDllUrl);
if(dllinstance==NULL) AfxMessageBox("can't open dll file");
其中strDllUrl是mydll.dll路径的字符串,这样程序才能找到它。::LoadLibrary获得参数标识的DLL文件的句柄。
获得句柄后,下面要获得函数地址以便执行它。有如下语句:
FARPROC proc;
proc=GetProcAddress(dllinstance,"go");
if(proc==NULL) AfxMessageBox("can't find function");
else proc();
FARPROC是一个远程过程指针,通过GetProcAddress获得函数的地址。它的两个参数就是dll文件句柄和函数的名字了。
然后FARPROC就可以和go一样的使用了,它就是go ,go 就是它。
而对于带参数的DLL中的函数,调用方法有所不同。因为对函数的调用是通过对它地址的引用进行的,这样,传入参数对不对,在函数调用程序的编译和联接过程中,无法知道其正确性。因此,要在调用程序中对DLL中带参数的函数做个声明,如mydll中的went,我们要做个声明如下:
typedef void (FAR __cdecl *MYWENT)(CString);
然后以类型MYWENT声明变量既可调用,如下:
MYWENT myproc;
myproc =(MYWENT)GetProcAddress(dllinstance,"went");
if(myproc ==NULL) AfxMessageBox("can't find function");
else myproc (“o-----yeah---------”);
注意声明的时候呢,由于DLL中WENT的定义为C语言调用规范,因此MYWENT前一定要用__cdecl,而VC中常用的__stdcall是PASCAL调用规范,不可以的。一定要注意。
方法①: 对DLL的工程DEBUG,
在DLL工程的Project Setting->Debug->Executable for debug session中加入你的.exe的路径和名字。
可以在dll中设置断点,.exe程序必须要调用dll中函数。
方法②: 有个更好的方法:(我也没试过)在settings/debug中category选additional dlls,
然后将你要调试的dll加进来。这样,即使你用loadlibrary动态加载dll,也可以加断点了。
在VS.net的测试中,还可以同时调试exe程序,调试dll实在系矛得弹。
调用DLL中的Dlg或SDI/MDI, 只是不能再使用APP类了,因为它是从CWinThread继承过来,内部的线程机制导出了问题的出现。
(1)对于调用DLL中的Dialog,很简单,直接调用就是
如: extern "C"
void LoadDialog()
{
CTestDlg dlg;
if (dlg.DoModal == IDOK)
{
//......
}
}
(2)对于调用DLL中的SDI/MDI, 不那么直接。需要保证Doc/View和MainFrame之间的关联,因此得保留原来在APP中用的CDocTempate类及对它的使用。为此,我们可以自己建一个类如CSDIMain来做接替原来APP中的工作(当然不用类,就直接用问题也不大,毕竟都是创建工作都是在堆上进行的),
如:
BOOL CSDIMain::InitInstance()
{
// 创建模板
if(m_pTemplate == NULL)
{
m_pTemplate = new CMultiDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CSDIForTestDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CSDIForTestView));
}
CSDIForTestDoc* pDocument = new CSDIForTestDoc;
// 创建新的frame
CFrameWnd* pFrame = m_pTemplate->CreateNewFrame(pDocument, NULL);
if (NULL == pFrame)
{
AfxMessageBox("Create frame failed");
return FALSE;
}
m_pTemplate->InitialUpdateFrame(pFrame, pDocument);
return TRUE;
}
原文链接: http://blog.csdn.net/augusdi/article/details/4642322