WINDOWS动态链接库--MFC规则动态链接库
第一代window程序员使用windows api进行编程,到了后来,微软推出MFC类库,于是,动态链接库进行了升级,可以在动态连接库中使用MFC的API,这就叫做MFC动态链接库,
其中MFC动态链接库又分为两种,MFC规则动态链接库和MFC扩展动态链接库,两者有些不同,一般来说规则动态链接库封装一些函数,方法和自己对MFC方法的封装,而扩展动态链接库
主要用于扩展MFC的控件,比如MFC的CLIST功能单一,就可以扩展成功能强大的表格,甚至可以扩展到像excel的功能.
今天说说MFC规则动态链接库,在VS中选择新建一个MFC DLL项目,就可以选择建立规则DLL还是扩展DLL,规则DLL没有WIN32动态链接库所有的DllMain函数,但是它包含有一个从
CWinApp继承下来的类,theapp在DLL初始化的时候自动调用DllMain,也就是说,类似于MFC编程WinMain函数被封装起来一样,MFC规则动态链接库封装了DllMain.
在调用规则动态链接库的时候,需要注意两个方面,第一是:静态链接的时候,不需要DLL进行模块状态的切换,第二是动态链接的时候,一定不能忘了切换模块.windows程序都有着自己的资源
ID,程序启动的时候,默认系统使用的是主线程的资源ID,程序调用的工具栏,菜单,等等资源,都与这个资源ID相关联,或者叫做资源模板.但是当DLL和调用程序都有着自己的资源模板的时候,主线程
调用DLL显示或者使用某个资源的时候,如果没有切换资源ID,DLL会使用主线程的资源,而不是使用DLL本身的资源,这样就会造成程序的混乱,所以,记住一点,在MFC规则动态链接库中,任何函数的第一行加上
AFX_MANAGE_STATE(AfxGetStaticModuleState());
该函数类似于单片机的中断压栈指令,他会将原先的资源模板替换成现在正在使用的实例本身的资源模板,当程序退出这个实例的时候,又会因为析构函数的作用自动恢复原先的资源模板,极为方便.
MFC规则DLL并非MFC应用程序,他所包含的CWinApp类并不包含消息循环,因为规则DLL不包括MFC的CWinApp::Run()机制,主消息泵依然由应用程序拥有,如果DLL生成非模态对话框,或者自己
的主窗口框架,则应用程序的主消息泵必须调用从DLL导出来的函数来调用CWinApp的PreTranslateMessage()函数,将消息传送到DLL中
虽然没有DLLMain函数,但是MFC规则DLL包含另一个用于初始化DLL环境的函数InitInstance(),该函数在DLL项目的主APP入口类文件中,原型如下
// 唯一的一个 CDinkMfcRegularDllApp 对象 CDinkMfcRegularDllApp theApp; // CDinkMfcRegularDllApp 初始化 BOOL CDinkMfcRegularDllApp::InitInstance()
{
CWinApp::InitInstance(); //初始化函数放在这里
dllMessage.Empty();
dllMessage.Append(TEXT("hello mfc regular dll")); return TRUE;
}
和win32 dll一样,规则DLL也可以导出所需的类和函数以及变量,不过有了更方便的方法,MFC定义了三个宏,帮助我们快速导出,分别是
AFX_EXT_API AFX_EXT_DATA AFX_EXT_CLASS 分别用于导出函数,变量和类,实际上对应的是这三个条件宏,如下
#ifndef AFX_EXT_DATA
#ifdef _AFXEXT
#define AFX_EXT_CLASS AFX_CLASS_EXPORT
#define AFX_EXT_API AFX_API_EXPORT
#define AFX_EXT_DATA AFX_DATA_EXPORT
#define AFX_EXT_DATADEF
#else
#define AFX_EXT_CLASS AFX_CLASS_IMPORT
#define AFX_EXT_API AFX_API_IMPORT
#define AFX_EXT_DATA AFX_DATA_IMPORT
#define AFX_EXT_DATADEF
#endif
#endif
#ifndef AFX_DATA_EXPORT
#define AFX_DATA_EXPORT __declspec(dllexport)
#endif
#ifndef AFX_DATA_IMPORT
#define AFX_DATA_IMPORT __declspec(dllimport)
#endif
#ifndef AFX_CLASS_EXPORT
#define AFX_CLASS_EXPORT __declspec(dllexport)
#endif
#ifndef AFX_CLASS_IMPORT
#define AFX_CLASS_IMPORT __declspec(dllimport)
#endif // for global APIs
#ifndef AFX_API_EXPORT
#define AFX_API_EXPORT __declspec(dllexport)
#endif
#ifndef AFX_API_IMPORT
#define AFX_API_IMPORT __declspec(dllimport)
#endif
我们只需要在项目->属性->VC++->预处理中定义 _AFXEXT这个宏就可以了.
下面是一个实际的代码演示,首先是头文件
#pragma once
#include "stdafx.h" //动态链接库版本
#define DINK_MFC_REGULAR_DLL_VERSION 0.01 #define DINK_MFC_REGULAR_DLL_NAME "DinkMfcRegularDll.dll"
#define DINK_MFC_REGULAR_LIB_NAME "DinkMfcRegularDll.lib" //变量
EXTERN_C CString AFX_EXT_DATA dllMessage;
//动态导出变量,需要三个东西,一个是导出函数的load时候的字符串
//第二个转换空指针到数据指针和实际数据的两个宏定义
#define DINK_REGULAR_DLL_VAR_DLLMESSAGE "dllMessage"
#define MAKE_REGULAR_DLL_DLLMESSAGE_PTR(ptr) ((CString*)ptr)
#define MAKE_REGULAR_DLL_DLLMESSAGE_VALUE(ptr) (*((CString*)ptr)) //全局方法
EXTERN_C void AFX_EXT_API PathAppendName(CString path,CString name,CString& dst);
typedef void (*DINK_REGULAR_FUNC_PATHAPPENDNAME)(CString path,CString name,CString& dst);
#define DINK_REGULAR_DLL_NAME_FUNC_PATHAPPENDNAME "PathAppendName" EXTERN_C UINT AFX_EXT_API ShowConfirmDialog(CString& showString); //存放所有需要导出的MFC规则DLL的函数,变量,类的头文件
//类不能动态导出,所以相对比较好一点
//个人文件处理函数
class AFX_EXT_CLASS CDinkFileLogic
{
public:
//检测指定文件是否存在
BOOL FileIsExist(CString filePath,CString fileName);
//读取指定文件的第一行文本
BOOL FileReadFirstLine(CString filePath,CString fileName,CString& readStr);
//删除指定文件
BOOL FileRemove(CString filePath,CString fileName);
//创建指定文件 force表示文件要是已经存在,是否删除并覆盖,为真,删除覆盖
BOOL FileCreate(CString filePath,CString fileName,BOOL force);
//创建文件,并添加事件后缀,withTime表示是否添加时间,为false,则创建文件仅仅包含日期
BOOL FileCreateByTime(CString filePath,CString fileName,BOOL force,BOOL withTime);
//文件写入一行,isCreate 表示当文件不存在是否主动创建
BOOL FileWriteLine(CString filePath,CString fileName,CString& writeStr,BOOL isCreate);
//文件移动,moveOrCopy为真,为剪切操作 为假,是拷贝操作,如果目标文件已经存在,返回失败
BOOL FileMove(CString SourceFilePath,CString SourceFileName,CString dstFilePath,CString dstFileName,BOOL moveOrCopy);
//文件移动,moveOrCopy为真,为剪切操作 为假,是拷贝操作,如果目标文件已经存在,默认覆盖该文件
BOOL FileMoveForce(CString SourceFilePath,CString SourceFileName,CString dstFilePath,CString dstFileName,BOOL moveOrCopy);
protected: private:
BOOL FileIsExist(CString fileFullPath);
}; //个人目录处理函数
class AFX_EXT_CLASS CDinkDirLogic
{
public:
//检测指定目录是否存在
BOOL DirIsExist(CString dirPath);
//创建指定目录,如果目录已经存在,返回OK
BOOL DirCreate(CString dirPath);
//创建指定目录,目录名带时间,withTime为真,带时分秒 为假,仅仅年月日
BOOL DirCreateByTime(CString dirPath,BOOL withTime);
//移除指定目录,只有在目录为空的时候才能执行
BOOL DirRemoveByEmpty(CString dirPath);
//移除指定目录,不管目录是否为空
BOOL DirRemoveNoEmpty(CString dirPath);
//检测目标文件夹是否还含有子文件,返回子文件个数
UINT IsDirContainFile(CString dirPath);
//获取指定文件夹的子文件夹名和子文件夹个数
UINT DirListOfDir(CString dirPath,CArray<CString>& dirArray);
//获取指定文件夹的子文件名列表和子文件个数
UINT FileListOfDir(CString dirPath,CArray<CString>& fileNameArray);
//移动指定目录,withFile表示是带文件的移动还是仅仅移动目录
//不会删除源文件夹
UINT DirMove(CString sourceDirPath,CString dstDirPath,BOOL withFile);
protected: private:
};
然后是与之对应的方法文件,数据文件和类文件,我习惯把三个文件分开,比较好维护,如下
#include "stdafx.h"
#include "DinkMfcRegularDllExtend.h" BOOL CDinkFileLogic::FileIsExist(CString filePath,CString fileName)
{
AFX_MANAGE_STATE(AfxGetModuleState());
//检测文件是否存在
CStdioFile test;
CString fileFullPath;
PathAppendName(filePath,fileName,fileFullPath);
if(test.Open(fileFullPath,CFile::modeRead))
{
//可以打开
test.Close();
return TRUE;
}
else
{
return FALSE;
}
} BOOL CDinkFileLogic::FileIsExist(CString fileFullPath)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CStdioFile test;
if(test.Open(fileFullPath,CFile::modeRead))
{
//可以打开
test.Close();
return TRUE;
}
else
{
return FALSE;
}
} BOOL CDinkFileLogic::FileReadFirstLine(CString filePath,CString fileName,CString& readStr)
{
AFX_MANAGE_STATE(AfxGetModuleState());
//读取制定文件第一行
CStdioFile test;
CString fileFullPath;
PathAppendName(filePath,fileName,fileFullPath);
if(test.Open(fileFullPath,CStdioFile::modeRead))
{
//打开了
readStr.Empty();
test.ReadString(readStr);
test.Close();
return TRUE;
}
else
{
//文件打不开
return FALSE;
}
} BOOL CDinkFileLogic::FileRemove(CString filePath,CString fileName)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CStdioFile test;
CString fileFullPath;
PathAppendName(filePath,fileName,fileFullPath);
CFile::Remove(fileFullPath);
return TRUE;
} BOOL CDinkFileLogic::FileCreate(CString filePath,CString fileName,BOOL force)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CStdioFile test;
CString fileFullPath;
PathAppendName(filePath,fileName,fileFullPath);
if(force == TRUE)
{
//强制创建,如果存在,清除源文件内容
if(test.Open(fileFullPath,CStdioFile::modeRead|CFile::modeCreate))
{
test.Close();
//已经存在文件
CFile::Remove(fileFullPath);
return TRUE;
}
else
{
//创建失败
return FALSE;
}
}
else
{
if(test.Open(fileFullPath,CFile::modeCreate|CFile::modeRead|CFile::modeNoTruncate))
{
test.Close();
return TRUE;
}
else
{
return FALSE;
}
}
} BOOL CDinkFileLogic::FileCreateByTime(CString filePath,CString fileName,BOOL force,BOOL withTime)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CString timeStr;
CTime time;
time = time.GetCurrentTime();
if(withTime == TRUE)
{
timeStr.Append(time.Format(TEXT("%Y-%m-%d-%H-%M-%S-")));
}
else
{
timeStr.Append(time.Format(TEXT("%Y-%m-%d-")));
}
CString fileFullName(TEXT(""));
fileFullName.Append(filePath);
fileFullName.Append(TEXT("\\"));
fileFullName.Append(timeStr);
fileFullName.Append(fileName);
CFile fileCreate;
if(force == TRUE)
{
if(fileCreate.Open(fileFullName,CFile::modeRead|CFile::modeCreate))
{
fileCreate.Close();
return TRUE;
}
else
{
return FALSE;
}
}
else
{
if(fileCreate.Open(fileFullName,CFile::modeRead|CFile::modeNoTruncate|CFile::modeCreate))
{
fileCreate.Close();
return TRUE;
}
else
{
return FALSE;
}
}
} BOOL CDinkFileLogic::FileWriteLine(CString filePath,CString fileName,CString& writeStr,BOOL isCreate)
{
AFX_MANAGE_STATE(AfxGetModuleState());
CString fullName;
PathAppendName(filePath,fileName,fullName);
CStdioFile dinkFile;
if(TRUE == isCreate)
{
//创建文件,如果文件已经存在就清空
if(dinkFile.Open(fullName,CFile::modeCreate|CFile::modeReadWrite))
{
dinkFile.SeekToEnd();
dinkFile.WriteString(writeStr);
dinkFile.Flush();
dinkFile.Close();
return TRUE;
}
else
{
//打开文件失败
return FALSE;
}
}
else
{
//如果文件已经存在就打开而且不清空,不存在就创建
if(TRUE == dinkFile.Open(fullName,CStdioFile::modeReadWrite|CFile::modeCreate|CFile::modeNoTruncate))
{
dinkFile.SeekToEnd();
dinkFile.WriteString(writeStr+TEXT("\n"));
dinkFile.Flush();
dinkFile.Close();
return TRUE;
}
else
{
//打开文件失败
return FALSE;
}
}
} BOOL CDinkFileLogic::FileMove(CString SourceFilePath,CString SourceFileName,CString dstFilePath,CString dstFileName,BOOL moveOrCopy)
{
AFX_MANAGE_STATE(AfxGetModuleState());
//文件移动
return FALSE;
} BOOL CDinkFileLogic::FileMoveForce(CString SourceFilePath,CString SourceFileName,CString dstFilePath,CString dstFileName,BOOL moveOrCopy)
{
AFX_MANAGE_STATE(AfxGetModuleState());
return FALSE;
}
#include "stdafx.h"
#include "DinkMfcRegularDllExtend.h"
#include "DinkConfirmResultDialog.h" void PathAppendName(CString path,CString name,CString& dst)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
dst.Empty();
if (path.IsEmpty())
{
dst.Append(TEXT(".\\"));
dst.Append(name);
}
else
{
dst.Append(path);
dst.Append(TEXT("\\"));
dst.Append(name);
}
} EXTERN_C UINT AFX_EXT_API ShowConfirmDialog(CString& showString)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
CDinkConfirmResultDialog dialog(showString);
int result;
result = dialog.DoModal();
return result;
}
#include "stdafx.h"
#include "DinkMfcRegularDllExtend.h" CString dllMessage;
对于资源模板,可以这样理解,应用程序及其调用的DLL每一个都有一个系统为之分配的HINSTANCE句柄,进程本身的模块句柄为0X400000(虚拟地址),而DLL的缺省句柄为0X00000000,如果程序加载多个DLL,则每个DLL都有一个不同的HINSSTANCE,
应用程序加载DLL的时候会对DLL进行重新定位.
HINSTANCE句柄对于加载资源十分重要,如果DLL需要加载资源就需要将资源句柄指定为DLL的资源句柄,应用程序也可以设置自己资源句柄为DLL的资源句柄,这样可以实现加载DLL的资源,具体在MFC中,切换资源句柄的方法有以下几种
1.DLL总调用AFX_MANAGE_STATE(AfxGetStaticModuleState()),主要用于DLL函数将应用程序的资源句柄切换为自身的资源句柄
2.在DLL接口函数调用
HINSTANCE exeHinstance = AfxGetResourceHandle();
AfxSetResourceHandle(theApp.m_instance);
//....接口代码
AfxSetResourceHandle(exeHinstance);
实现的效果和第一种类似
3.应用程序自身切换,这种方法可以实现exe自身加载不同的资源
HINSTANCE exe_hinstance = GetModuleHandle(NULL);
HINSTANCE dll_hinstance = GetModuleHandle("DLL名称");
AfxSetResourceHandle(dll_hinstance);
//调用dll函数,或者调用dll资源
AfxSetResourceHandle(exe_hinstance);
以下为静态调用MFC规则DLL的演示程序,如下
//静态调用变量
#include "..\\DinkMfcRegularDll\DinkMfcRegularDllExtend.h"
#pragma comment(lib,DINK_MFC_REGULAR_LIB_NAME) void CDinkMfcRegularDllCallDlg::OnBnClickedButtonStaticShowVar()
{
// TODO: 在此添加控件通知处理程序代码
CString showString(TEXT("load var str is : "));
showString.Append(dllMessage);
MessageBox(showString,TEXT("message"),MB_OK);
} //静态
void CDinkMfcRegularDllCallDlg::OnBnClickedButtonStaticFuncCall()
{
// TODO: 在此添加控件通知处理程序代码
CString str1(TEXT("F:\\MFC\\DinkDll\\DinkDll\\Release"));
CString str2(TEXT("DinkMfcRegularDll.dll"));
CString dstStr;
PathAppendName(str1,str2,dstStr);
MessageBox(dstStr,TEXT("message"),MB_OK);
} //静态调用类
void CDinkMfcRegularDllCallDlg::OnBnClickedButtonStaticClassCall()
{
// TODO: 在此添加控件通知处理程序代码
CDinkFileLogic dinkFileLogic;
CString str1(TEXT("F:\\MFC\\DinkDll\\DinkDll\\Release"));
CString str2(TEXT("Hello.txt"));
CString dstStr;
if(dinkFileLogic.FileCreate(str1,str2,FALSE))
{
if(dinkFileLogic.FileWriteLine(str1,str2,CString("hello world"),FALSE))
{
MessageBox(TEXT("write file ok"),TEXT("message"),MB_ICONINFORMATION|MB_OK);
}
else
{
MessageBox(TEXT("write file failed"),TEXT("error"),MB_ICONERROR|MB_OK);
}
}
else
{
MessageBox(TEXT("file create failed"),TEXT("error"),MB_ICONERROR|MB_OK);
}
} void CDinkMfcRegularDllCallDlg::OnBnClickedButtonShowDialog()
{
// TODO: 在此添加控件通知处理程序代码
UINT result;
result = ShowConfirmDialog(CString("hello world"));
CString confirmShowMessage(TEXT(""));
confirmShowMessage.AppendFormat(TEXT("dialog return value is %d"),result);
MessageBox(confirmShowMessage,TEXT("message"),MB_ICONINFORMATION|MB_OK);
}
以下为动态调用DLL
//动态变量显式
void CDinkMfcRegularDllCallDlg::OnBnClickedButtonDynamicShowVar()
{
// TODO: 在此添加控件通知处理程序代码
HMODULE dllModule;
CString* str;
dllModule = AfxLoadLibrary(TEXT(DINK_MFC_REGULAR_DLL_NAME));
if(dllModule != NULL)
{
str = MAKE_REGULAR_DLL_DLLMESSAGE_PTR(GetProcAddress(dllModule,DINK_REGULAR_DLL_VAR_DLLMESSAGE));
CString showString(TEXT("load var str is : "));
showString.Append(*str);
MessageBox(showString,TEXT("message"),MB_OK);
AfxFreeLibrary(dllModule);
}
else
{
MessageBox(TEXT("lib load failed"),TEXT("error"),MB_ICONERROR);
}
} //动态调用函数
void CDinkMfcRegularDllCallDlg::OnBnClickedButtonDynamicCallFunc()
{
// TODO: 在此添加控件通知处理程序代码
HMODULE dllModule;
DINK_REGULAR_FUNC_PATHAPPENDNAME pathAddFunc;
dllModule = AfxLoadLibrary(TEXT(DINK_MFC_REGULAR_DLL_NAME));
if(dllModule != NULL)
{
pathAddFunc = (DINK_REGULAR_FUNC_PATHAPPENDNAME)(GetProcAddress(dllModule,DINK_REGULAR_DLL_NAME_FUNC_PATHAPPENDNAME));
CString str1(TEXT("F:\\MFC\\DinkDll\\DinkDll\\Release"));
CString str2(TEXT("DinkMfcRegularDll.dll"));
CString dstStr;
pathAddFunc(str1,str2,dstStr);
MessageBox(dstStr,TEXT("message"),MB_OK);
AfxFreeLibrary(dllModule);
}
else
{
MessageBox(TEXT("lib load failed"),TEXT("error"),MB_ICONERROR);
}
}
MFC规则DLL,1.动态的切换应用程序的资源.2.能够在DLL中使用MFC的API
但是MFC dll也不能动态的调用dll中的类,要使用类,使用静态调用.
WINDOWS动态链接库--MFC规则动态链接库的更多相关文章
- stdafx.h、stdafx.cpp是干什么用的?为什么我的每一个cpp文件都必须包含stdafx.h? Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编
sstdafx.h.stdafx.cpp是干什么用的?为什么我的每一个cpp文件都必须包含stdafx.h? Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编译程序也要 ...
- Dynamic Property Wizard 添加类提示 ATL类只能添加到MFC EXE 和MFC规则DLL项目或完全支持ATL的项目 错误提示解决方式
在重新打开OPM项目添加ATL动态属性向导Dynamic Property Wizard提示错误 ATL类只能添加到MFC EXE 和MFC规则DLL项目或完全支持ATL的项目. 有效的解决方式,右键 ...
- MFC创建动态链接库DLL并调用方法详解
实例一: 1.创建一个动态链接库工程,如login_dll. 2.在原工程头文件或者新建头文件如showdlg.h定义动态链接库的导出函数,代码如下: #include "stdafx.h& ...
- windows编程命名规则
转自:http://blog.sina.com.cn/s/blog_52cbfc3f0100fdy6.html 匈牙利命名法是一种编程时的命名规范.基本原则是:变量名=属性+类型+对象描述.其中每一对 ...
- 静态链接库(lib)、动态链接库(dll)与动态链接库的导入库(lib)
静态链接库与动态链接库相对应.动态链接库的导入库不同于以上两种库. 1.静态链接库(lib) 程序编译一般需经编辑.编译.连接.加载和运行几个步骤.在我们的应用中,有一些公共代码是需要反复使用 ...
- Python的扩展接口[2] -> 动态链接库DLL[0] -> 动态链接库及辅助工具
动态链接库 / Dynamic Link Library 目录 动态链接库简介 函数封装DLL 组件对象模型COM 如何判断.dll文件是COM还是DLL 辅助工具 1 动态链接库简介 / DLL I ...
- VS2010创建动态链接库并且使用动态链接库DLL
1.编写动态链接库文件 dll和lib文件 例子: 在新建VS工程时选择DLL 空项目 ----------hello.h-------- #include <stdio.h> #prag ...
- windows防火墙添加规则
#include <windows.h> #include <crtdbg.h> #include <netfw.h> #include <objbase.h ...
- Windows防火墙端口规则设置新建方法
from:https://jingyan.baidu.com/article/2a1383289fd094074a134ff0.html Windows防火墙有什么用呢?它是电脑的一道安全屏障,可以有 ...
随机推荐
- OpenGL红宝书例子2.2 uniform变量的使用
1. 简单介绍一下OpenGL可编程渲染管线的流程 顶点着色 --> 细分着色 --> 几何着色 --> 片元着色 --> 计算着色 一般我们主要参与的阶段是顶点着色和片元着色 ...
- spring多个数据源配置
sys.properties中的内容 jdbc.driverClassName=oracle.jdbc.driver.OracleDriver DB.url=jdbc\:oracle\:thin\:@ ...
- LightOJ 1336 Sigma Function 算数基本定理
题目大意:f(n)为n的因子和,给出 n 求 1~n 中f(n)为偶数的个数. 题目思路:算数基本定理: n=p1^e1*p2^e1 …… pn^en (p为素数): f(n)=(1+p1+p1^2+ ...
- 4位开锁<dfs>
题意: 有一个四位密码的锁,每一位是1~9的密码,1跟9相连.并且相邻的连个密码位可以交换.每改变一位耗时1s,给出锁的当前状态和密码,求最少解锁时间. 思路: 用bfs枚举出所有相邻交换的情况,并记 ...
- php 执行效率
用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量,单引号则 不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的“函数”(译注:PHP手册中 ...
- C# Socket的TCP通讯 异步 (2015-11-07 10:07:19)转载▼
异步 相对于同步,异步中的连接,接收和发送数据的方法都不一样,都有一个回调函数,就是即使不能连接或者接收不到数据,程序还是会一直执行下去,如果连接上了或者接到数据,程序会回到这个回调函数的地方重新往下 ...
- Python科学计算学习一 NumPy 快速处理数据
1 创建数组 (1) array(boject, dtype=None, copy=True, order=None, subok=False, ndmin=0) a = array([1, 2, 3 ...
- HDU - 1865 1string(大数)
题目链接:http://acm.hust.edu.cn/vjudge/contest/121397#problem/F http://acm.hdu.edu.cn/showproblem.php?pi ...
- Flex Cairngrom框架浅浅印象
VO ↓ Model ← Delegate ← Command ↓ ↑ ↓ ...
- [LeetCode] Magical String 神奇字符串
A magical string S consists of only '1' and '2' and obeys the following rules: The string S is magic ...