VS2005创建自己的DLL库
使用vs建立动态链接库dll过程和使用方法

使用vs建立动态链接库dll的过程和使用方法创建动态链接库(DLL)的过程可以分为几个步骤。
我将使用Visual Studio 来演示这个过程:创建DLL的步骤:1.打开Visual Studio,选择“文件”->“新建”->“项目”。
2.在新项目窗口中,选择“Visual C++”->“Windows桌面向导应用程序”。
3.输入项目名称和位置,然后点击“确定”。
4.在“解决方案资源管理器”中,右键单击项目名称->添加->新建项。
5.在“添加新项”窗口中,选择“DLL”,输入DLL名称,然后点击“添加”。
编写DLL代码:现在你已经有了一个空的DLL,你可以开始编写你的代码了。
例如,你可以添加以下代码到你的.cpp文件中:在这个例子中,我们创建了一个简单的函数add,它接收两个整数并返回它们的和。
extern "C"部分告诉编译器使用C链接规则创建导出函数,__declspec(dllexport)部分使得该函数可以从DLL中导出。
编译和生成DLL:在Visual Studio中,你可以通过点击“生成”菜单然后选择“生成解决方案”来编译和生成你的DLL。
如果编译成功,你可以在你的项目文件夹的Debug或Release 文件夹中找到生成的DLL文件。
使用DLL:使用DLL的过程可以分为几个步骤:1.加载DLL:使用Windows API函数LoadLibrary可以加载DLL。
例如:HMODULE hMod = LoadLibrary(TEXT("MyDLL.dll"));。
这个函数会返回一个模块句柄,如果DLL加载成功的话。
2.获取函数地址:使用GetProcAddress函数可以获取DLL中函数的地址。
例如:add_proc = (int (*)(int, int))GetProcAddress(hMod, "add");。
VS2005 Web引用程序打包并安装数据库

VS2005 Web引用程序打包并安装数据库一个解决方案中可能会包含多个类库项目和一个网站,打包过程如下:1、在【解决方案资源管理器】中【右键-添加-新建项目】,左侧选择【其他类型项目】,右侧选择【安装项目】,如下图:2、点击【确定】后,右侧【文件系统】选项卡中选择【应用程序文件夹】-【添加】-【项目输出】,类库项目选择添加【主输出】,网站选择添加【内容文件】3、在网站的制作过程中可能用到一些其他的BLL组件,也需要添加进来,还是选择【应用程序文件夹】-【添加】-【程序集】,选择你网站BIN文件夹下的一些BLL4、因为要带数据库带包,我是采用打包程序利用系统存储过程附加MDF和LDF 文件的方法,所以【应用程序文件夹】中还需要【添加-文件】,将数据库的MDF 和LDF文件添加进来,如果安装的需要在控制面板的添加删除程序列表中有图标的话,也需要将ICO图标文件添加进来。
5、设置安装项目的常用属性:Author:作者Manufactuer:公司Title:安装程序的标题AddRemoveProgramsIco:设置为添加进来的ICO文件如果不带数据库安装的话,可以将安装项目直接生成就可以了,如果Debug设置为True,则生成的MSI文件在Debug文件夹中,如果为False,生成的MSI文件在Release文件夹中。
6、在【解决方案资源管理器】中,右键,添加【新建项目】-【Visual C#】-【类库】,建立数据库安装程序,类库建好后,将默认的Class1.cs文件删除,右键,添加【新建项】-【安装程序类】,下面主要是此类的代码。
7、安装程序类的代码:1using ponentModel;2using System.Configuration.Install;3using System.Collections; //以下引入4using System.Collections.Specialized;5using System.Data;6using System.Data.SqlClient;7using System.Reflection;8using System.Xml;910namespace DbClass11 {12 [RunInstaller(true)]13public partial class InstallDB : Installer14 {15///<summary>16///必需的设计器变量,均来自于安装程序的“自定义操作”视图中的设置17///</summary>18private string hostname;19private string username;20private string userpassword;21private string dbname;2223public InstallDB()24 {25 InitializeComponent();26 }2728private string CreateSqlStr()29 {30string sqlstr = "";31string datafile = Context.Parameters["installdir"] + @"FlowerShop.mdf";32string logfile = Context.Parameters["installdir"] + @"FlowerShop_log.ldf";33sqlstr = "EXEC sp_attach_db @dbname ='"+ Context.Parameters["dbname"] + "',@filename1='"+ datafile + "',@filename2='" + logfile + "'";34return sqlstr;35 }3637private void ExecuteSql(string DatabaseName, string SqlStr) 38 {39string SqlConnectionStr = @"server="+ hostname + ";uid=" + username + ";pwd=" + userpassword;40SqlConnection myConnection = newSqlConnection(SqlConnectionStr);41SqlCommand myCommand = new SqlCommand(SqlStr, myConnection);42 myCommand.Connection.Open();43 myCommand.Connection.ChangeDatabase(DatabaseName);44 myCommand.ExecuteNonQuery();45 myCommand.Connection.Close();46 }4748private void AddFlowerShopDataBase()49 {50 ExecuteSql("pubs", CreateSqlStr());51 }5253private void ModifyXML()54 {55string XMLdir = Context.Parameters["installdir"] + @"Web.config";56 XmlNodeReader reader = null;57 XmlTextWriter writer = null;58 XmlDocument doc = new XmlDocument();59 doc.Load(XMLdir);60 reader = new XmlNodeReader(doc);61writer = new XmlTextWriter(XMLdir, System.Text.Encoding.UTF8);6263try64 {65while (reader.Read())66 {67if(reader.NodeType == XmlNodeType.Element && == "connectionStrings")68 {69string strContent = reader.ReadInnerXml(); 70strContent = "<add name=\"strShop\" connectionString=\"server=" + hostname + ";database=" + dbname + ";uid=" + username + ";pwd=" + userpassword + "\" providerName=\"System.Data.SqlClient\"/>";71 XmlNode root = doc.DocumentElement;72XmlElement elem = doc.CreateElement("connectionStrings");73 elem.InnerXml = strContent;74root.ReplaceChild(elem, root.ChildNodes[1]);75 doc.Save(writer);76break;77 }78 }79 }80finally81 {82if (reader != null)83 reader.Close();84 }85 }8687public override void Install(IDictionary stateSaver)88 {89base.Install(stateSaver);90 hostname = Context.Parameters["hostname"];91 username = Context.Parameters["username"];92 userpassword = Context.Parameters["userpassword"];93 dbname = Context.Parameters["dbname"];94this.AddFlowerShopDataBase();95this.ModifyXML();96 }97 }98 }【注意】最后一个方法Install方法中Parameters中的键名都是与接下来要添加的自定义操作中的变量名要保持一致的,包括上面用到的installdir。
c#创建DLL详解

内容简介介绍如何是使用C#来完成动态链接库的创建和使用、动态链接库对代码有很好的封装、能很好的保护源代码。
使用图例完整的演示。
使用软件vs2005以及以上版本均可步骤和方法1.新建一个类库。
2.3.编写一个简单的类库实例,例如:DllTest在默认名为:calss1.cs里编写代码一下是一个简单的:在控制台显示“你以成功调用了动态连接!”sing System;using System.Collections.Generic;using System.Text;namespace DllTest{public class Class1{public void ShowMessage(){Console.WriteLine("你以成功调用了动态连接!");Console.ReadLine();}}}4.配置输出,在解决方案上右击——属性,在应用程序选卡中需要注意一下三个内容。
1.程序集名称2.默认命名空间3.输出类型1.DllTest2.DllTest3.类库这些对我调用来说很有用!5.生成dll,在菜单栏在生成里点击“生成dlltest”,或者按shfit+F6生成成功,在目录下能看到生成的Dll:6.调用该dll,新建一个控制台应用程序,来实现该dll的调用。
新建一个DLLExample。
7.在新建的项目内添加引用,引用该dll。
8.9.在“查找范围里找到,我们生成的dll,点击确定。
在解决方案中显示如下内容,说明你添加成功!10.11.这时我就可以在程序中调用了。
在program.cs中添加如下代码:using System;using System.Collections.Generic;using System.Text;//必须添加using System.Runtime.InteropServices;using DllTest;namespace DllExample{class Program{//DllTest,我们的动态链接库[DllImport("DllTest.dll")]//这个很重要publicstaticexternvoid ShowMessage();//public static extern void ShowMessage();static void Main(string[] args){//实例化DllTest.Class1 i = new Class1();//调用动态链接库的方法i.ShowMessage();}}}12.运行结果:注意事项其他应用程序可使用同样的方法调用!。
C#下开发及调用dll文件的方法

C#下开发及调用dll文件的方法在.net中,可调用的dll(动态链接库)文件其实就是一个类库。
我们可以通过写一个类,然后把它编译成dll文件形式,在其他的项目中就可以直接调用此编译好的dll文件,而不用重复写这个类的代码。
下面详细介绍此过程:一、开发dll文件(1)打开vs2005,新建项目中模板选择“类库”(2)在解决资源管理器里面添加一文件夹“First”,在其中添加两个类MathAdd和MathMinus,在其父目录里直接添加一个名为yun(写这个类的时候,我已经晕了,不知道取什么名字好,于是就yun了)的类。
下面是各个类的代码,注意类前一定要加上public,不然这个类会被当做是私有的,不能够被引用,当初我就是犯了这个错误,弄个了好久才想起,真是追悔莫及啊。
类中的方法为静态或非静态都可以。
MathAdd类代码using System;using System.Collections.Generic;using System.Text;namespace noo.First{public class MathAdd{public int add( int a,int b){return a + b;}public static int Muti(int a, int b){int mutiSum;mutiSum = a * b;return mutiSum;}}}MathMinus类代码using System;using System.Collections.Generic;using System.Text;namespace noo.First{public class MathMinus{public static int minus(int a, int b){return a - b;}}}yun类代码using System;using System.Collections.Generic;using System.Text;namespace noo{public class yun{public int add(int a, int b,int c){return a + b-c;}}到此,dll代码其实已经写好,这里我们可以发现,其实dll文件就是一个一个封装好的类库而已。
在VC中创建DLL文件的方法步骤祥解

今天教大家在中创建文件地方法步骤,一起来学习一下,并不是很难地,相信聪明地你一看就会.一动态链接库.制作地步骤:()新建工程,工程名为,选择类型.文档收集自网络,仅用于个人学习()地内容如下:以下是引用片段:"" () ( )本文所有地例子只有一个即加法函数. 文档收集自网络,仅用于个人学习()地内容如下:以下是引用片段:""""""(,,){;}"" () ( , ) 文档收集自网络,仅用于个人学习{;}()编译之后产生了与两个文件..使用方法:().隐式调用法:将和拷贝到需要应用该地工程地目录下,将拷贝到产生地应用程序地目录下,并在需要应用该中地函数地文件中添加如下几行:文档收集自网络,仅用于个人学习以下是引用片段:""(,"");().显示调用法:将和拷贝到需要应用该地工程地目录下,将拷贝到产生地应用程序地目录下,并在需要应用该中地函数地文件中包含头文件,如:文档收集自网络,仅用于个人学习以下是引用片段:""同时还需要在>>> 地框中增加这个库.文档收集自网络,仅用于个人学习二动态链接库.制作地步骤:()新建()工程,工程名为,选择类型.文档收集自网络,仅用于个人学习()在生成地文件后面增加下面几行:以下是引用片段:( , ){;}()在生成地文件后面增加如下:以下是引用片段:;表示第一个函数是()编译后会产生两个文件.使用方法()隐式调用法:将拷贝到需要应用该地工程地目录下,将拷贝到产生地应用程序地目录下,并在需要应用该中地函数地文件中添加如下几行:文档收集自网络,仅用于个人学习注意这里没有在中声明函数,所以不能直接包含来声明函数.以下是引用片段:(,"");( , );当然如果你地中有很多函数,那可以另外写个,包含所有地函数声明,然后直接将头文件包含进去文档收集自网络,仅用于个人学习()显示调用法:与地调用方法一样,不需要(,"");,但是需要在>>> 地框中增加这个库.文档收集自网络,仅用于个人学习。
Visual_Studio_2005教程(MFC)

Visual C++ 2005教程目录第一章:Windows程序开发简介 (2)DOS中用户使用软件的方式 (2)Windows中用户使用软件的方式 (3)Windows中程序运行的机制 (4)第二章:Windows编程初步 (6)第一个程序 (6)查看系统库函数的帮助说明 (19)设置控件的属性 (20)完成的程序 (24)输入数据的控件 (26)第三章:Windows编程进阶 (33)列表框控件 (34)单选框控件 (36)组合框控件 (37)复选框控件 (40)列表框控件 (44)图片控件 (48)更多的功能 (49)完整的示例代码 (50)第四章:Windows图形编程 (61)创建菜单 (61)创建工具条 (67)绘制图形 (74)第五章:数据库编程 (80)数据库简介 (80)数据库的建立 (80)ODBC数据源的设置方法 (86)数据库的访问方法 (91)一个实际的例子 (95)第六章:线程机制 (114)线程的概念 (114)线程的状态 (114)线程的优先级 (115)线程的创建和管理 (116)一个演示示例 (117)前台线程和后台线程 (119)线程优先级 (120)挂起线程和恢复线程 (121)终止线程 (121)时钟线程 (122)第七章:网络编程 (123)TCP/IP协议原理介绍 (123)Internet概述 (123)TCP/IP协议 (124)网络应用程序的运行模式 (127).NetFrameWork中的Socket类库 (128)访问网页 (132)一个聊天程序 (132)第一章Windows程序开发简介开发运行在Windows操作系统中的软件需要掌握关于Windows系统下编程的技术,现在业界有多种成熟的Windows开发技术,在本书中,将介绍使用.Net Framework来开发Windows 软件。
那什么是.Net Framework呢?简单的说.Net Framework就是一个C++的类库,专门用来简化Windows程序设计的。
VS2005环境下生成静态lib库及调用方法

VS2005环境下生成静态lib库及调用方法生成lib方法:步骤1:新建一个空项目,建一个头文件如Test.h#pragma once#ifdef __cplusplusextern "C" {#endifint GetMin(int a, int b);#ifdef __cplusplus}#endif//其实只要 int GetMin(int a, int b);这么一句语言也会通过,其他的语句仅仅表明一个头文件在很多情况下并不是这么简单的,会有很多的定义步骤2:新建一个源文件如Test.cpp#include "Test.h"int GetMin(int a, int b){return (a < b) ? a : b;}//这里定义一个两者取较小值的函数步骤3:选择配置属性->常规,配置类型选“静态库(.lib)”,确定后再编译,这时会在工程所在文件的debug文件夹下产生一个.lib的静态链接库。
至此,生成工作完成。
调用lib方法:调用方法有两种:第一种:项目设置中引用,在项目的属性中设置。
第二种:在代码中使用 #progma comment(lib,"lib文件名");这里介绍第一种方法。
右键单击项目,有三个地方需要添加lib库的目录和头文件的目录。
步骤一:右键单击项目—>属性—>配置属性—>C/C++—>常规—>附加包含目录在其中填入头文件所在的目录,可以是绝对路径,也可以相对路径(“..”两个点表示上一层目录,“.”一个点表示同级目录,这是相对你工程所在的目录而言的)步骤二:右键单击项目—>属性—>配置属性—>链接器—>常规—>附加库目录在其中填入lib库的目录,也可以是相对或绝对路径。
步骤三:右键单击项目—>属性—>配置属性—>链接器—>输入—>附加依赖项在其中填入lib库的名称,如:Test.lib步骤四:新建一个控制台应用程序进行测试#include "stdafx.h"#include "..\..\Test\Test\Test.h" //注意:这里要include进头文件并且指明路径,或者你可以把头文件直接考到你的工程目录下,并在工程的头文件下把.h文件包含进来,这样只要用 #include “Test.h”就可以#include "iostream"using namespace std;int main(){ int a = 11, b = 12;int c;while(1){c = GetMin(a, b);cout<<c<<endl;}return 0;}。
VS2005创建动态库和调用动态库函数

如何创建动态链接库和调用动态链接库(入门教程)声明:此教程是我初学动态链接库时写的,作为自己的学习笔记,同时也希望能够帮助还在迷惑的初学者。
我的学习资料主要来自于互联网,因此也想把自己的东西分享给大家。
希望共同交流。
如果你已经是高手,请绕开。
开发平台:Windows xp sp3编译环境:VS2005开发语言:C/C++VB版本:VB6.0希望我们共同交流看法,请联系bai_yechuang@陈搏于2012,8,27日废话少说,直接进入正题。
一点击“OK”点击“Next”下面是.cpp和对应的.h文件,先浏览一遍导出DLL库分为2种,一种是用关键字__declspec(dllexport)一种是使用def文件。
1.使用关键字导出DLL编写自己的三个函数//1.求个数的最大数DLLTEST_API int MaxFun(int x,int y){return((x>y)?(x):(y));}//2.求和DLLTEST_API int AddFun(int x,int y){return(x+y);}//3.打印DLLTEST_API void PrintFun(void){std::cout<<"调用动态库函数"<<std::endl; }DLLTEST_API表示此函数导出看看编译结果下面我们写一个控制台程序来调用此函数把dlltest.dll dlltest.lib dlltest.h三个文件考到本地工程目录下面程序如下:结果:只需要将dlltest.dll文件复制到本地工程目录下。
结果:VB界面如下:2个按钮对应2个DLL函数的功能,有一个函数没有参数和返回值在VB中无法使用我们暂且不用。
其遇到的种种错误再此就不多说,直接说正确的调用方法。
如果要想其它平台能够调用VC DLL库,需要在以前的基础上做一些修改。
1.使用def文件的方式导出DLL库之前的dlltest.h就不需要啦。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
1VS2005创建DLL使用VS2005创建自己的动态链接库,这样就不用看到DLL文件有抵触情感了。
一、打开VS2005软件,创建DLL工程。
起名ceshi1.1)2)点击下一步,应用程序类型为DLL,空工程。
3)完成,一个新的DLL工程设置完毕,接下来编辑源码添加头文件,命名为ceshi1.h,编辑内容:#ifndef CESHI1_H#define CESHI1_H //防止重复定义#include<iostream> //头文件引用#if defined DLL_EXPORT //源文件需引用下一函数#define DECLDIR__declspec(dllexport)//就是这个#else#define DECLDIR __declspec(dllimport)#endifextern"C"{DECLDIR int add(int a, int b); //函数声明DECLDIR void function(void);}#endif解释:VC中有两种方式导出DLL文件中的函数1)使用 __declspec关键字。
2)创建模板定义文件(Module_Definithion File)即.def文件。
在此使用第一种方法:__declspec(dllexport)作用是导出函数符号到DLL的一个存储类中。
在头文件中定义#define DECLDIR __declspec(dllexport)宏来运行这个函数。
使用条件编译,在源文件中宏定义 #define DLL_EXPORT 来运行这个函数。
//****************************************************************************** 创建源文件 ceshi1.cpp#include<iostream>#define DLL_EXPORT#include"ceshi1.h"extern"C"{//定义Dll中的所有函数DECLDIR int add(int a, int b){return a+b;}DECLDIR void function(void){std::cout<<"DLL called"<<std::endl;}}编译工程,生成ceshi1.dll文件和ceshi1.lib文件(注:找到工程目录,这两个文件在外面的debug文件夹下)。
二、使用创建好的DLL库文件创建一个控制台应用程序1)隐式链接:连接到.lib文件,首先将ceshi1.h头文件,ceshi1.dll动态库文件,ceshi1.lib静态库文件放在控制台应用程序工程的目录中,即源文件所在的文件夹里。
添加源文件ceshi2.cpp,编码:#pragma comment(lib,"ceshi1.lib")//链接.lib文件#include"ceshi1.h"//包含dll的头文件#include<iostream>int main(){function();std::cout<<add(25,25)<<std::endl;getchar();return 0;}//******************************************************************************2)显式链接只加载.dll文件,但需用到函数指针和Windows 函数,不需要.lib文件和.h头文件。
#include<iostream>#include<windows.h>typedef int (*AddFunc)(int, int);typedef void (*FunctionFunc)(void);//函数指针int main(){AddFunc _AddFunc;FunctionFunc _FunctionFunc;//HINSTANCE实例句柄(即一个历程的入口地址)HINSTANCE hInstLibrary = LoadLibraryA("ceshi1.dll");//注意,此时的LoadLibraryA()窄字符集和LoadLibraryW()宽字符集的区别,后有介绍。
if(hInstLibrary == NULL){FreeLibrary(hInstLibrary);//释放DLL获得的内存,若句柄无效}//获得函数的入口地址,还需类型转换_AddFunc = (AddFunc)GetProcAddress(hInstLibrary,"add");_FunctionFunc = (FunctionFunc)GetProcAddress(hInstLibrary,"function");if(_AddFunc==NULL || _FunctionFunc ==NULL)//确定是否成功。
{FreeLibrary(hInstLibrary);}std::cout<<_AddFunc(25,25)<<std::endl;_FunctionFunc();getchar();FreeLibrary(hInstLibrary);return 0;}//****************************************************************************** Windows 的执行文件可以划分为两种形式:程序和动态连接库(DLLs)。
一般程序运行是用.EXE文件,但应用程序有时需要调用存储在DLL 中的函数。
当我们调用Windows 中的API 函数的时候,实际上就是调用存储在DLL 中的函数。
在如下几种情况下,调用DLL 是合理的:1)不同的程序使用相同的DLL ,这样只需要将DLL 在内存中装载一次,节省了内存的开销。
2)当某些内容需要升级的时候,如果使用DLL 只需要改变DLL 就可以了,而不需要把整个程序都进行变动。
3)由于DLL 是独立于语言的,所以,当不同语言习惯的人共同开发一个大型项目的时候,使用DLL 便于程序系统的交流,当然,Delphi开发的DLL 也可以在诸如Visual BASIC,C++ 等系统中使用。
2C语言创建DLL只是要在公开的接口函数声明前面加上几个特定的修饰符。
//**********example1.h*********************************************************** #ifndef EXAMPLE1_H#define EXAMPLE1_H#define DLLIMPORT __declspec(dllexport)DLLIMPORT void HelloWorld(void);#endif//******example1.c*************************************************************** #include"example1.h"#include<windows.h>#include<stdio.h>#include<stdlib.h>DLLIMPORT void HelloWorld(void){MessageBox(0,TEXT("Hello World from DLL!\n"),TEXT("Hi"),MB_ICONINFORMATION); }BOOL APIENTRY DllMain(HINSTANCE hInst,DWORD reason,LPVOID reserved){switch(reason){case DLL_PROCESS_ATTACH:break;case DLL_PROCESS_DETACH:break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;}return true;}__declspec(dllexport)标志着后面这个函数将成为对外的接口,使用包含在DLL中的函数,必须将其导入,导入操作通过dllimport来完成,dllexport和dllimport都是VC和BC所支持的关键字,但不能被自身格式所使用,通用格式为__declspec(dllexport)和__declspec(dllimport),为了简化,用宏名代替,若程序被编译成C++程序,同时希望C程序亦可使用,需要增加”C”的链接说明,#define DLLEXPORT extern “C” __declspec(dllexport),就避免了标准C++命名损坏。
、、有错。
BOOL APIENTRY DllMain()说明:1、每个DLL必须有一个入口点,DllMain()是入口函数,负责初始化(initialization)和结束(termination)工作,每当一个新的进程或该进程的新的线程访问DLL时,或者不再使用DLL时,或结束时,都将调用DllMain。
但是使用terminate Process或terminate Thread结束进程和线程,不会调用DllMain。
DllMain()函数的原型:BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_resong_for_call, LPVOID lpreserved) {switch(ul_reason_for_call){case DLL_PROCESS_ATTACH:…case DLL_THREAD_ATTACH:…case DLL_PROCESS_DETTACH:…case DLL_THREAD_DETTACH:…}return true;}参数:hMoudle:是动态库被调用时所传递来的一个指向自己的句柄(实际上,它是指向_DGROUP段的一个选择符);HINSTANCEul_reason_for_call:是一个说明动态库被调原因的标志。
当进程或线程装入或卸载动态连接库的时候,操作系统调用入口函数,并说明动态连接库被调用的原因。
它所有的可能值为:DLL_PROCESS_ATTACH: 进程被调用;DLL_THREAD_ATTACH: 线程被调用;DLL_PROCESS_DETACH: 进程被停止;DLL_THREAD_DETACH: 线程被停止;lpReserved:是一个被系统所保留的参数。