A. EDI 的系统组成是什么
EDI系统由EDI技术标准、EDI软件及硬件、EDI技术通信网络3个要素组成。EDI装置由增压泵、电去离子(EDI)膜块、直流稳压电源、流量计、仪表等组成。
EDI系统是利用混合离子交换树脂吸附给水中的阴、阳离子,同时被吸附的离子又在直流电压的作用下,分别透过阴、阳离子交换膜而被去除的过程。电渗析器的一对电极之间,通常由阴膜,将一定数量的EDI单元间用网状网隔开,构成浓室和淡室。
淡室水中阳离子向负极迁移透过阳膜,被浓室中的阴膜截留,水中阴离子向正极方向迁移阴膜,被浓室中的阳膜截留,淡水又在单元组两端设置阴/阳离子分别穿过阴、阳离子交换膜进入浓水室而被去除。而通过浓水室的水将离子带出系统,成为浓水。从而达到淡化、提纯、浓缩或精制的目的。
(1)在edi软件结构中扩展阅读
EDI膜堆是EDI工作的核心,膜堆是由阴、阳离子交换膜,淡、浓水室隔板,离子交换树脂和正负电极等按一定规则排列组合并夹紧所构成的单元。膜堆中淡 水室相当于一个混床,使用的离子交换树脂是磺酸型阳树脂和季胺型阴树脂,淡水室中的树脂必须装填紧密。
EDI膜堆系统在每个单元内都有两类不同的室,待除盐的淡水室和收集所除去杂质离子的浓水室。淡水室中用混匀的阴、阳离子交换树脂填满,这些树脂位于两个膜之间,只允许阳离子透过的阳离子交换膜及只允许阴离子透过的阴离子交换膜。
B. EDI的软件结构中包含哪些模块
用户接口模块
内部接口模块
报文生成及处理模块
该模块有两个功能:
a.接受来自用户接口模块和内部接口模块的命令和信息,按照EDI标准生成订单、发票等各种EDI报文和单证,经格式转换模块处理之后,由通信模块经EDI网络发给其它EDI用户。
b.自动处理由其它EDI系统发来的报文。在处理过程中要与本单位信息系统相联,获取必要信息并给其它EDI系统答复,同时将有关信息送给本单位其它信息系统。
如因特殊情况不能满足对方的要求,经双方EDI系统多次交涉后不能妥善解决的,则把这一类事件提交用户接口模块,由人工干预决策。
格式转换模块
所有的EDI单证都必须转换成标准的交换格式,转换过程包括语法上的压缩、嵌套、代码的替换以及必要的EDI语法控制字符。在格式转换过程中要进行语法检查,对于语法出错的EDI报文应拒收并通知对方重发。
通信模块
该模块是EDI系统与EDI通信网络的接口。包括执行呼叫、自动重发、合法性和完整性检查、出错报警、自动应答、通信记录、报文拼装和拆卸等功能。
除以上这些基本模块外,EDI系统还必须具备一些基本功能。
a.命名和寻址功能
EDI的终端用户在共享的名字当中必须是唯一可标识的。命名和寻址功能包括通信和鉴别两个方面。
在通信方面,EDI是利用地址而不是名字进行通信的。因而要提供按名字寻址的方法,这种方法应建立在开放系统目录服务ISO9594(对应ITU-T X.500)基础上。在鉴别方面,有若干级必要的鉴别,即通信实体鉴别,发送者与接收者之间的相互鉴别等。
b.安全功能
EDI的安全功能应包含在上述所有模块中。它包括以下一些内容:
终端用户以及所有EDI参与方之间的相互验证;
数据完整性;
EDI参与方之间的电子(数字)签名;
否定EDI操作活动的可能性;
密钥管理。
c.语义数据管理功能
完整语义单元(CSU)是由多个信息单元(IU)组成的。其CSU和IU的管理服务功能包括:
IU应该是可标识和可区分的;
IU必须支持可靠的全局参考;
应能够存取指明IU属性的内容,如语法、结构语义、字符集和编码等;
应能够跟踪和对IU定位;
对终端用户提供方便和始终如一的访问方式。
EDI的操作过程
当今世界通用的EDI通信网络,是建立在MHS数据通信平台上的信箱系统,其通信机制是信箱间信息的存储和转发。具体实现方法是在数据通信网上加挂大容量信息处理计算机,在计算机上建立信箱系统,通信双方需申请各自的信箱,其通信过程就是把文件传到对方的信箱中。文件交换由计算机自动完成,在发送文件时,用户只需进入自己的信箱系统。
EDI可以看做是MHS通信子平台,图2.2、图2.3、图2. 4分别表示了EDI在计算机通信网络七层协议中的地位和作用、EDI信箱系统通信和交换原理、以及完整的通信流程。
通信流程中各功能模块说明如下:
映射(Mapping)—生成EDI平面文件
EDI平面文件(Flat File)是通过应用系统将用户的应用文件(如:单证、票据)或数据库中的数据,映射成的一种标准的中间文件。这一过程称为映射(Mapping)。
平面文件是用户通过应用系统直接编辑、修改和操作的单证和票据文件,它可直接阅读、显示和打印输出。
翻译(Translation)—生成EDI标准格式文件
其功能是将平面文件通过翻译软件(Translation Software)生成EDI标准格式文件。
EDI标准格式文件,就是所谓的EDI电子单证,或称电子票据。它是EDI用户之间进行贸易和业务往来的依据。EDI标准格式文件是一种只有计算机才能阅读的ASCII文件。它是按照EDI数据交换标准(即EDI标准)的要求,将单证文件(平面文件)中的目录项,加上特定的分割符、控制符和其它信息,生成的一种包括控制符、代码和单证信息在内的ASCII码文件。
通信
这一步由计算机通信软件完成。用户通过通信网络,接入EDI信箱系统,将EDI电子单证投递到对方的信箱中。
EDI信箱系统则自动完成投递和转接,并按照X.400(或X.435)通信协议的要求,为电子单证加上信封、信头、信尾、投送地址、安全要求及其它辅助信息。
EDI文件的接收和处理
接收和处理过程是发送过程的逆过程。首先需要接收用户通过通信网络接入EDI信箱系统,打开自己的信箱,将来函接收到自己的计算机中,经格式校验、翻译、映射还原成应用文件。最后对应用文件进行编辑、处理和回复。
在实际操作过程中,EDI系统为用户提供的EDI应用软件包,包括了应用系统、映射、翻译、格式校验和通信连接等全部功能。其处理过程,用户可看作是一个“黑匣子”,完全不必关心里面具体的过程。
图2.5是一家贸易公司用EDI通信网络实现报关的工作流程示意图。
EDI的通信服务
EDI的通信环境(EDIME)由一个EDI通信系统(EDIMS)和多个EDI用户(EDIMG)组成,见图2.6。EDI的开发、应用就是通过计算机通信网络实现的,它主要有以下三种方式。
点对点(PTP)方式
点对点方式即EDI按照约定的格式,通过通信网络进行信息的传递和终端处理,完成相互的业务交往。早期的EDI通信一般都采用此方式,但它有许多缺点,如当EDI用户的贸易伙伴不再是几个而是几十个甚至几百个时,这种方式很费时间,需要许多重复发送。同时这种通信方式是同步的,不适于跨国家、跨行业之间的应用。
近年来,随着技术进步,这种点对点的方式在某些领域中仍旧有用,但会有所改进。新方法采用的是远程非集中化控制的对等结构,利用基于终端开放型网络系统的远程信息业务终端,用特定的应用程序将数据转换成EDI报文,实现国际间的EDI报文互通。
增值网(VAN)方式
它是那些增值数据业务(VADS)公司,利用已有的计算机与通信网络设备,除完成一般的通信任务外,增加EDI的服务功能。VADS公司提供给EDI用户的服务主要是租用信箱及协议转换,后者对用户是透明的。信箱的引入,实现了EDI通信的异步性,提高了效率,降低了通信费用。另外,EDI报文在VADS公司自已的系统(即VAN中)中传递也是异步的,即存储转发的。
VAN方式尽管有许多优点,但因为各增值网的EDI服务功能不尽相同,VAN系统并不能互通,从而限制了跨地区、跨行业的全球性应用。同时,此方法还有一个致命的缺点,即VAN只实现了计算机网络的下层,相当于OSI参考模型的下三层。而EDI通信往往发生在各种计算机的应用进程之间,这就决定了EDI应用进程与VAN的联系相当松散,效率很低。
MHS方式
信息处理系统MHS是ISO和ITU-T联合提出的有关国际间电子邮件服务系统的功能模型。它是建立OSI开放系统的网络平台上,适应多样化的信息类型,并通过网络连接,具有快速、准确、安全、可靠等特点。它是以存储转发为基础的、非实时的电子通信系统,非常适合作为EDI的传输系统。MHS为EDI创造一个完善的应用软件平台,减少了EDI设计开发上的技术难度和工作量。ITU-T X.435/F.435规定了EDI信息处理系统和通信服务,把EDI和MHS作为OSI应用层的正式业务。EDI与MHS互连,可将EDI报文直接放入MHS的电子信箱中,利用MHS的地址功能和文电传输服务功能,实现EDI报文的完善传送。
EDI信息处理系统由信息传送代理(MTA)、EDI用户代理(EDI-UA)、EDI信息存储(EDI-MS)和访问单元(AU)组成,见图2.7。MTA完成建立接续、存储/转发,由多个MTA组成MTS系统。EDI在MHS中的传递过程见图2.8。
EDI-MS存储器位于EDI-UA和MTA之间,它如同一个资源共享器或邮箱,帮助EDI-UA发送、投递、存储和取出EDI信息。同时EDI-MS把EDI UA接收到的报文变成EDI报文数据库,并提供对该数据库的查询、检索等功能。为有利于检索,EDI-MS将报文的信封、信首、信体映射到MS信息实体的不同特征域,并提供自动转发及自动回送等服务。
EDI-UA是电子单证系统与传输系统之间的接口。它的任务是利用MTS的功能来传输电子单证。EDI-UA将它处理的信息对象分作两种:一种称为EDI报文(EDIM),另一种称为EDI回执(EDIN)。前者是传输电子单证的,后一种是报告接收结果的。EDI-UA和MTS共同构成了EDI信息系统(EDI-MS),EDI-MS和EDI用户又一起构成了EDI通信环境(EDIME)。
EDI与MHS结合,大大促进了国际EDI业务的发展。为实现EDI的全球通信,EDI通信系统还使用了X.500系列的目录系统(DS)。
DS可为全球EDI通信网的补充、用户的增长等目录提供增、删、改功能,以获得名址网络服务、通信能力列表、号码查询等一系列属性的综合信息。EDI、MHS和DS的结合,使信息通信有一了个新飞跃,为EDI的发展提供了广阔的前景。EDI、HS和DS的综合网络见图2.9。
C. 可以在多线程 DLL 的接口函数中创建线程吗
比较大的应用程序都由很多模块组成,这些模块分别完成相对独立的功能,它们彼此协作来完成整个软件系统的工作。可能存在一些模块的功能较为通用,在构造其它软件系统时仍会被使用。在构造软件系统时,如果将所有模块的源代码都静态编译到整个应用程序 EXE 文件中,会产生一些问题:一个缺点是增加了应用程序的大小,它会占用更多的磁盘空间,程序运行时也会消耗较大的内存空间,造成系统资源的浪费;另一个缺点是,在编写大的 EXE 程序时,在每次修改重建时都必须调整编译所有源代码,增加了编译过程的复杂性,也不利于阶段性的单元测试。
Windows 系统平台上提供了一种完全不同的较有效的编程和运行环境,你可以将独立的程序模块创建为较小的 DLL (Dynamic Linkable Library) 文件,并可对它们单独编译和测试。在运行时,只有当 EXE 程序确实要调用这些 DLL 模块的情况下,系统才会将它们装载到内存空间中。这种方式不仅减少了 EXE 文件的大小和对内存空间的需求,而且使这些 DLL 模块可以同时被多个应用程序使用。Windows 自己就将一些主要的系统功能以 DLL 模块的形式实现。
一般来说,DLL 是一种磁盘文件,以.dll、.DRV、.FON、.SYS 和许多以 .EXE 为扩展名的系统文件都可以是 DLL。它由全局数据、服务函数和资源组成,在运行时被系统加载到调用进程的虚拟空间中,成为调用进程的一部分。如果与其它 DLL 之间没有冲突,该文件通常映射到进程虚拟空间的同一地址上。DLL 模块中包含各种导出函数,用于向外界提供服务。DLL 可以有自己的数据段,但没有自己的堆栈,使用与调用它的应用程序相同的堆栈模式;一个 DLL 在内存中只有一个实例;DLL 实现了代码封装性;DLL 的编制与具体的编程语言及编译器无关。
在 Win32 环境中,每个进程都复制了自己的读/写全局变量。如果想要与其它进程共享内存,必须使用内存映射文件或者声明一个共享数据段。DLL 模块需要的堆栈内存都是从运行进程的堆栈中分配出来的。Windows 在加载 DLL 模块时将进程函数调用与 DLL 文件的导出函数相匹配。Windows 操作系统对 DLL 的操作仅仅是把 DLL 映射到需要它的进程的虚拟地址空间里去。DLL 函数中的代码所创建的任何对象(包括变量)都归调用它的线程或进程所有。
调用方式
1、静态调用方式:由编译系统完成对 DLL 的加载和应用程序结束时 DLL 卸载的编码(如还有其它程序使用该 DLL,则 Windows 对 DLL 的应用记录减1,直到所有相关程序都结束对该 DLL 的使用时才释放它,简单实用,但不够灵活,只能满足一般要求。
隐式的调用:需要把产生动态连接库时产生的 .LIB 文件加入到应用程序的工程中,想使用 DLL 中的函数时,只须说明一下。隐式调用不需要调用 LoadLibrary() 和 FreeLibrary()。程序员在建立一个 DLL 文件时,链接程序会自动生成一个与之对应的 LIB 导入文件。该文件包含了每一个 DLL 导出函数的符号名和可选的标识号,但是并不含有实际的代码。LIB 文件作为 DLL 的替代文件被编译到应用程序项目中。
当程序员通过静态链接方式编译生成应用程序时,应用程序中的调用函数与 LIB 文件中导出符号相匹配,这些符号或标识号进入到生成的 EXE 文件中。LIB 文件中也包含了对应的 DL L文件名(但不是完全的路径名),链接程序将其存储在 EXE 文件内部。
当应用程序运行过程中需要加载 DLL 文件时,Windows 根据这些信息发现并加载 DLL,然后通过符号名或标识号实现对 DLL 函数的动态链接。所有被应用程序调用的 DLL 文件都会在应用程序 EXE 文件加载时被加载在到内存中。可执行程序链接到一个包含 DLL 输出函数信息的输入库文件(.LIB文件)。操作系统在加载使用可执行程序时加载 DLL。可执行程序直接通过函数名调用 DLL 的输出函数,调用方法和程序内部其 它的函数是一样的。
2、动态调用方式:是由编程者用 API 函数加载和卸载 DLL 来达到调用 DLL 的目的,使用上较复杂,但能更加有效地使用内存,是编制大型应用程序时的重要方式。
显式的调用:是指在应用程序中用 LoadLibrary 或 MFC 提供的 AfxLoadLibrary 显式的将自己所做的动态连接库调进来,动态连接库的文件名即是上面两个函数的参数,再用 GetProcAddress() 获取想要引入的函数。自此,你就可以象使用如同本应用程序自定义的函数一样来调用此引入函数了。在应用程序退出之前,应该用 FreeLibrary 或 MFC 提供的 AfxFreeLibrary 释放动态连接库。直接调用 Win32 的 LoadLibary 函数,并指定 DLL 的路径作为参数。LoadLibary 返回 HINSTANCE 参数,应用程序在调用 GetProcAddress 函数时使用这一参数。GetProcAddress 函数将符号名或标识号转换为 DLL 内部的地址。程序员可以决定 DLL 文件何时加载或不加载,显式链接在运行时决定加载哪个 DLL 文件。使用 DLL 的程序在使用之前必须加载(LoadLibrary)加载DLL从而得到一个DLL模块的句柄,然后调用 GetProcAddress 函数得到输出函数的指针,在退出之前必须卸载DLL(FreeLibrary)。
Windows将遵循下面的搜索顺序来定位 DLL:
包含EXE文件的目录
进程的当前工作目录
Windows系统目录
Windows目录
列在 Path 环境变量中的一系列目录
MFC中的DLL
Non-MFC DLL:指的是不用 MFC 的类库结构,直接用 C 语言写的 DLL,其输出的函数一般用的是标准 C 接口,并能被 非 MFC 或 MFC 编写的应用程序所调用。
Regular DLL:和下述的 Extension DLLs 一样,是用 MFC 类库编写的。明显的特点是在源文件里有一个继承 CWinApp 的类。其又可细分成静态连接到 MFC 和动态连接到 MFC 上的。
静态连接到 MFC 的动态连接库只被 VC 的专业 版和企业版所支持。该类 DLL 应用程序里头的输出函数可以被任意 Win32 程序使用,包括使用 MFC 的应用程序。输入函数有如下形式:
extern "C" EXPORT YourExportedFunction();
如果没有 extern "C" 修饰,输出函数仅仅能从 C++ 代码中调用。
DLL 应用程序从 CWinApp 派生,但没有消息循环。
动态链接到 MFC 的 规则 DLL 应用程序里头的输出函数可以被任意 Win32 程序使用,包括使用 MFC 的应用程序。但是,所有从 DLL 输出的函数应该以如下语句开始:
AFX_MANAGE_STATE(AfxGetStaticMoleState( ))
此语句用来正确地切换 MFC 模块状态。
Regular DLL能够被所有支持 DLL 技术的语言所编写的应用程序所调用。在这种动态连接库中,它必须有一个从 CWinApp 继承下来的类,DLLMain 函数被 MFC 所提供,不用自己显式的写出来。
Extension DLL:用来实现从 MFC 所继承下来的类的重新利用,也就是说,用这种类型的动态连接库,可以用来输出一个从 MFC 所继承下来的类。它输出的函数仅可以被使用 MFC 且动态链接到 MFC 的应用程序使用。可以从 MFC 继承你所想要的、更适于你自己用的类,并把它提供给你的应用程序。你也可随意的给你的应用程序提供 MFC 或 MFC 继承类的对象指针。Extension DLL使用 MFC 的动态连接版本所创建的,并且它只被用 MFC 类库所编写的应用程序所调用。Extension DLLs 和 Regular DLLs 不一样,它没有从 CWinApp 继承而来的类的对象,所以,你必须为自己 DLLMain 函数添加初始化代码和结束代码。
和规则 DLL 相比,有以下不同:
1、它没有从 CWinApp 派生的对象;
2、它必须有一个 DLLMain 函数;
3、DLLMain 调用 AfxInitExtensionMole 函数,必须检查该函数的返回值,如果返回0,DLLMmain 也返回 0;
4、如果它希望输出 CRuntimeClass 类型的对象或者资源,则需要提供一个初始化函数来创建一个 CDynLinkLibrary 对象。并且,有必要把初始化函数输出;
5、使用扩展 DLL 的 MFC 应用程序必须有一个从 CWinApp 派生的类,而且,一般在InitInstance 里调用扩展 DLL 的初始化函数。
DLL入口函数
1、每一个 DLL 必须有一个入口点,DLLMain 是一个缺省的入口函数。DLLMain 负责初始化和结束工作,每当一个新的进程或者该进程的新的线程访问 DLL 时,或者访问 DLL 的每一个进程或者线程不再使用DLL或者结束时,都会调用 DLLMain。但是,使用 TerminateProcess 或 TerminateThread 结束进程或者线程,不会调用 DLLMain。
DLLMain的函数原型:
BOOL APIENTRY DLLMain(HANDLE hMole,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:
.......
return TRUE;
}
}
参数:
hMoudle:是动态库被调用时所传递来的一个指向自己的句柄(实际上,它是指向_DGROUP段的一个选择符);
ul_reason_for_call:是一个说明动态库被调原因的标志。当进程或线程装入或卸载动态连接库的时候,操作系统调用入口函数,并说明动态连接库被调用的原因。它所有的可能值为:
DLL_PROCESS_ATTACH: 进程被调用;
DLL_THREAD_ATTACH: 线程被调用;
DLL_PROCESS_DETACH: 进程被停止;
DLL_THREAD_DETACH: 线程被停止;
lpReserved:是一个被系统所保留的参数;
2、_DLLMainCRTStartup
为了使用 "C" 运行库 (CRT,C Run time Library) 的 DLL 版本(多线程),一个 DLL 应用程序必须指定 _DLLMainCRTStartup 为入口函数,DLL 的初始化函数必须是 DLLMain。
_DLLMainCRTStartup 完成以下任务:当进程或线程捆绑(Attach) 到 DLL 时为 "C" 运行时的数据 (C Runtime Data) 分配空间和初始化并且构造全局 "C++"对象,当进程或者线程终止使用DLL(Detach) 时,清理 C Runtime Data 并且销毁全局 "C++" 对象。它还调用 DLLMain 和 RawDLLMain 函数。
RawDLLMain 在 DLL 应用程序动态链接到 MFC DLL 时被需要,但它是静态链接到 DLL 应用程序的。在讲述状态管理时解释其原因。
关于调用约定
动态库输出函数的约定有两种:调用约定和名字修饰约定。
1)调用约定(Calling convention):决定函数参数传送时入栈和出栈的顺序,由调用者还是被调用者把参数弹出栈,以及编译器用来识别函数名字的修饰约定。
函数调用约定有多种,这里简单说一下:
1、__stdcall 调用约定相当于16位动态库中经常使用的 PASCAL 调用约定。在32位的 VC++5.0 中PASCAL 调用约定不再被支持(实际上它已被定义为__stdcall。除了__pascal 外,__fortran 和__syscall也不被支持),取而代之的是 __stdcall 调用约定。两者实质上是一致的,即函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,但不同的是函数名的修饰部分(关于函数名的修饰部分在后面将详细说明)。
_stdcall 是 Pascal 程序的缺省调用方式,通常用于 Win32 API 中,函数采用从右到左的压栈方式,自己在退出时清空堆栈。VC 将函数编译后会在函数名前面加上下划线前缀,在函数名后加上 "@" 和参数的字节数。
2、C 调用约定(即用__cdecl 关键字说明)按从右至左的顺序压参数入栈,由调用者把参数弹出栈。对于传送参数的内存栈是由调用者来维护的(正因为如此,实现可变参数的函数只能使用该调用约定)。另外,在函数名修饰约定方面也有所不同。
_cdecl 是 C 和 C++ 程序缺省的调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用 _stdcall 函数的大。函数采用从右到左的压栈方式。VC 将函数编译后会在函数名前面加上下划线前缀。 它是 MFC 缺省调用约定。
3、__fastcall 调用约定是 "人" 如其名,它的主要特点就是快,因为它是通过寄存器来传送参数的(实际上,它用 ECX 和 EDX 传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈),在函数名修饰约定方面,它和前两者均不同。
_fastcall方式的函数采用寄存器传递参数,VC 将函数编译后会在函数名前面加上"@"前缀,在函数名后加上"@"和参数的字节数。
4、thiscall 仅仅应用于 "C++" 成员函数。this 指针存放于 CX 寄存器,参数从右到左压。thiscall 不是关键词,因此不能被程序员指定。
5、naked call采用 1-4 的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。
naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec 共同使用。
关键字 __stdcall、__cdecl 和 __fastcall 可以直接加在要输出的函数前,也可以在编译环境的 Setting...\C/C++ \Code Generation 项选择。当加在输出函数前的关键字与编译环境中的选择不同时,直接加在输出函数前的关键字有效。它们对应的命令行参数分别为/Gz、/Gd 和 /Gr。缺省状态为/Gd,即__cdecl。
要完全模仿 PASCAL 调用约定首先必须使用 __stdcall 调用约定,至于函数名修饰约定,可以通过其它方法模仿。还有一个值得一提的是 WINAPI 宏,Windows.h 支持该宏,它可以将出函数翻译成适当的调用约定,在 WIN32 中,它被定义为 __stdcall。使用 WINAPI 宏可以创建自己的 APIs。
2)名字修饰约定
1、修饰名(Decoration name)
"C" 或者 "C++" 函数在内部(编译和链接)通过修饰名识别。修饰名是编译器在编译函数定义或者原型时生成的字符串。有些情况下使用函数的修饰名是必要的,如在模块定义文件里头指定输出"C++"重载函数、构造函数、析构函数,又如在汇编代码里调用"C""或"C++"函数等。
修饰名由函数名、类名、调用约定、返回类型、参数等共同决定。
2、名字修饰约定随调用约定和编译种类(C或C++)的不同而变化。函数名修饰约定随编译种类和调用约定的不同而不同,下面分别说明。
a、C编译时函数名修饰约定规则:
__stdcall 调用约定在输出函数名前加上一个下划线前缀,后面加上一个"@"符号和其参数的字节数,格式为 _functionname@number。
__cdecl调用约定仅在输出函数名前加上一个下划线前缀,格式为 _functionname。
__fastcall调用约定在输出函数名前加上一个"@"符号,后面也是一个"@"符号和其参数的字节数,格式为@functionname@number。
它们均不改变输出函数名中的字符大小写,这和PASCAL调用约定不同,PASCAL约定输出的函数名无任何修饰且全部大写。
b、C++编译时函数名修饰约定规则:
__stdcall调用约定:
1、以"?"标识函数名的开始,后跟函数名;
2、函数名后面以"@@YG"标识参数表的开始,后跟参数表;
3、参数表以代号表示:
X——void,
D——char,
E——unsigned char,
F——short,
H——int,
I——unsigned int,
J——long,
K——unsigned long,
M——float,
N——double,
_N——bool,
....
PA——表示指针,后面的代号表明指针类型,如果相同类型的指针连续出现,以"0"代替,一个"0"代表一次重复;
4、参数表的第一项为该函数的返回值类型,其后依次为参数的数据类型,指针标识在其所指数据类型前;
5、参数表后以"@Z"标识整个名字的结束,如果该函数无参数,则以"Z"标识结束。
其格式为"?functionname@@YG*****@Z"或"?functionname@@YG*XZ",
例如
int Test1(char *var1,unsigned long)-----“?Test1@@YGHPADK@Z”
void Test2() -----“?Test2@@YGXXZ”
__cdecl调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YA"。
__fastcall调用约定:
规则同上面的_stdcall调用约定,只是参数表的开始标识由上面的"@@YG"变为"@@YI"。
VC++对函数的省缺声明是"__cedcl",将只能被C/C++调用。
关于DLL的函数
动态链接库中定义有两种函数:导出函数(export function)和内部函数(internal function)。导出函数可以被其它模块调用,内部函数在定义它们的DLL程序内部使用。
输出函数的方法有以下几种:
1、传统的方法
在模块定义文件的 EXPORT 部分指定要输入的函数或者变量。语法格式如下:
entryname[=internalname] [@ordinal[NONAME]] [DATA] [PRIVATE]
其中:
entryname 是输出的函数或者数据被引用的名称;
internalname 同 entryname;
@ordinal 表示在输出表中的顺序号(index);
NONAME 仅仅在按顺序号输出时被使用(不使用 entryname );
DATA 表示输出的是数据项,使用 DLL 输出数据的程序必须声明该数据项为 _declspec(DLLimport)。
上述各项中,只有 entryname 项是必须的,其他可以省略。
对于"C"函数来说,entryname 可以等同于函数名;但是对 "C++" 函数(成员函数、非成员函数)来说,entryname 是修饰名。可以从 .map 映像文件中得到要输出函数的修饰名,或者使用DUMPBIN /SYMBOLS 得到,然后把它们写在 .def 文件的输出模块。DUMPBIN 是VC提供的一个工具。
如果要输出一个 "C++" 类,则把要输出的数据和成员的修饰名都写入 .def 模块定义文件。
2、在命令行输出
对链接程序 LINK 指定 /EXPORT 命令行参数,输出有关函数。
3、使用 MFC 提供的修饰符号 _declspec(DLLexport)
在要输出的函数、类、数据的声明前加上 _declspec(DLLexport) 修饰符表示输出。__declspec(DLLexport) 在 C 调用约定、C 编译情况下可以去掉输出函数名的下划线前缀。extern "C" 使得在 C++ 中使用 C 编译方式成为可能。在"C++"下定义"C"函数需要加 extern "C" 关键词。用 extern "C" 来指明该函数使用 C 编译方式。输出的 "C" 函数可以从 "C" 代码里调用。
例如,在一个 C++ 文件中,有如下函数:
extern "C"
其输出函数名为:Test
MFC提供了一些宏,就有这样的作用。
AFX_CLASS_IMPORT:__declspec(DLLexport)
AFX_API_IMPORT:__declspec(DLLexport)
AFX_DATA_IMPORT:__declspec(DLLexport)
AFX_CLASS_EXPORT:__declspec(DLLexport)
AFX_API_EXPORT:__declspec(DLLexport)
AFX_DATA_EXPORT:__declspec(DLLexport)
AFX_EXT_CLASS: #ifdef _AFXEXT
AFX_CLASS_EXPORT
#else
AFX_CLASS_IMPORT
AFX_EXT_API:#ifdef _AFXEXT
AFX_API_EXPORT
#else
AFX_API_IMPORT
AFX_EXT_DATA:#ifdef _AFXEXT
AFX_DATA_EXPORT
#else
AFX_DATA_IMPORT
像 AFX_EXT_CLASS 这样的宏,如果用于 DLL 应用程序的实现中,则表示输出(因为_AFX_EXT被定义,通常是在编译器的标识参数中指定该选项 /D_AFX_EXT);如果用于使用DLL的应用程序中,则表示输入(_AFX_EXT没有定义)。
要输出整个的类,对类使用_declspec(_DLLexpot);要输出类的成员函数,则对该函数使用_declspec(_DLLexport)。如:
class AFX_EXT_CLASS CTextDoc : public CDocument
{
…
}
extern "C" AFX_EXT_API void WINAPI InitMYDLL();
这几种方法中,最好采用第三种,方便好用;其次是第一种,如果按顺序号输出,调用效率会高些;最次是第二种。
模块定义文件(.DEF)
模块定义文件(.DEF)是一个或多个用于描述 DLL 属性的模块语句组成的文本文件,每个DEF文件至少必须包含以下模块定义语句:
第一个语句必须是LIBRARY语句,指出DLL的名字;
EXPORTS 语句列出被导出函数的名字;将要输出的函数修饰名罗列在 EXPORTS 之下,这个名字必须与定义函数的名字完全一致,如此就得到一个没有任何修饰的函数名了。
可以使用DESCRIPTION语句描述DLL的用途(此句可选);
";"对一行进行注释(可选)。 DLL程序和调用其输出函数的程序的关系
1、DLL与进程、线程之间的关系
DLL模块被映射到调用它的进程的虚拟地址空间。
DLL使用的内存从调用进程的虚拟地址空间分配,只能被该进程的线程所访问。
DLL的句柄可以被调用进程使用;调用进程的句柄可以被DLL使用。
DLL使用调用进程的栈。
2、关于共享数据段
DLL定义的全局变量可以被调用进程访问;DLL可以访问调用进程的全局数据。使用同一DLL的每一个进程都有自己的DLL全局变量实例。如果多个线程并发访问同一变量,则需要使用同步机制;对一个DLL的变量,如果希望每个使用DLL的线程都有自己的值,则应该使用线程局部存储(TLS,Thread Local Strorage)。
在程序里加入预编译指令,或在开发环境的项目设置里也可以达到设置数据段属性的目的.必须给这些变量赋初值,否则编译器会把没有赋初始值的变量放在一个叫未被初始化的数据段中。
D. EDI 的系统组成是什么
EDI系统由EDI技术标准、EDI软件及硬件、EDI技术通信网络3个要素组成。装置由增压泵、电去离子(EDI)膜块、直流稳压电源、流量计、仪表等组成。
EDI系统是利用混合离子交换树脂吸附给水中的阴、阳离子,同时被吸附的离子又在直流电压的作用下,分别透过阴、阳离子交换膜而被去除的过程。电渗析器的一对电极之间,通常由阴膜,将一定数量的EDI单元间用网状网隔开,构成浓室和淡室。
淡室水中阳离子向负极迁移透过阳膜,被浓室中的阴膜截留,水中阴离子向正极方向迁移阴膜,被浓室中的阳膜截留,淡水又在单元组两端设置阴/阳离子分别穿过阴、阳离子交换膜进入浓水室而被去除。而通过浓水室的水将离子带出系统,成为浓水。从而达到淡化、提纯、浓缩或精制的目的。
(4)在edi软件结构中扩展阅读
EDI膜堆是EDI工作的核心,膜堆是由阴、阳离子交换膜,淡、浓水室隔板,离子交换树脂和正负电极等按一定规则排列组合并夹紧所构成的单元。膜堆中淡 水室相当于一个混床,使用的离子交换树脂是磺酸型阳树脂和季胺型阴树脂,淡水室中的树脂必须装填紧密。
EDI膜堆系统在每个单元内都有两类不同的室,待除盐的淡水室和收集所除去杂质离子的浓水室。淡水室中用混匀的阴、阳离子交换树脂填满,这些树脂位于两个膜之间,只允许阳离子透过的阳离子交换膜及只允许阴离子透过的阴离子交换膜。
E. 电子商务主要学什么
电子商务源于英文ELECTRONIC
COMMERCE,简写为EC。顾名思义,其内容包含两个方面,一是电子方式,二是商贸活动。
电子商务指的是利用简单、快捷、低成本的电子通讯方式,买卖双方不谋面地进行各种商贸活动。
电子商务可以通过多种电子通讯方式来完成。简单的,比如你通过打电话或发传真的方式来与客户进行商贸活动,似乎也可以称作为电子商务;但是,现在人们所探讨的电子商务主要是以EDI(电子数据交换)和INTERNET来完成的。尤其是随着INTERNET技术的日益成熟,电子商务真正的发展将是建立在INTERNET技术上的。所以也有人把电子商务简称为IC(INTERNET
COMMERCE)。
从贸易活动的角度分析,电子商务可以在多个环节实现,由此也可以将电子商务分为两个层次,较低层次的电子商务如电子商情、电子贸易、电子合同等;最完整的也是最高级的电子商务应该是利用INTENET网络能够进行全部的贸易活动,即在网上将信息流、商流、资金流和部分的物流完整地实现,也就是说,你可以从寻找客户开始,一直到洽谈、订货、在线付(收)款、开据电子发票以至到电子报关、电子纳税等通过INTERNET一气呵成。
要实现完整的电子商务还会涉及到很多方面,除了买家、卖家外,还要有银行或金融机构、政府机构、认证机构、配送中心等机构的加入才行。由于参与电子商务中的各方在物理上是互不谋面的,因此整个电子商务过程并不是物理世界商务活动的翻版,网上银行、在线电子支付等条件和数据加密、电子签名等技术在电子商务中发挥着重要的不可或缺的作用。
晕了,我是电子商务专业的,老师当时只是说可以到公司上班,为设计会议材料,安排会议室,再就是建网站,做做网页