数据库调用

2024-07-31

数据库调用(共9篇)

数据库调用 篇1

数据库软件是以计算机平台为基础, 针对数据存储以及调用设计的一款智能化软件, 其使用非常方便, 智能化和集成化的能力也非常强。对于现有的技术而言, 如何对数据库软件程序开发过程中, 针对数据的存储以及数据的调用进行设计成为了目前数据库开发过程中的主要内容。本文将针对以上两点进行重点探讨, 并对未来的数据库数据处理进行进一步的分析。

数据库软件是目前应用较为广泛的软件之一, 由于信息数据技术的发展, 为数据提供了更为方便与快捷的存储以及调用方式。电子化设备普及让数据库使用平台更加广泛, 也让数据形式更加多样化。但是, 面临用户日益提高的需求, 计算机平台基础的数据库软件开发也遇到了一些问题。在对数据进行处理的过程中, 如何有效进行智能化管理, 在存储和调用过程中如何改变传统的手工录入方式, 让存储与调用都更加智能化, 是目前数据库软件遇到的主要问题。基于此, 将通过研究数据库软件的程序开发原理, 并结合现有技术理论, 探讨如何有效地完成数据存储与调用指令设计。

1 数据库软件的特点与技术分析

数据库软件是目前计算机数据处理中最为常用的软件之一, 利用其强大的数据处理功能, 可以很好地实现数据存储、数据调用以及数据分析等功能。对于目前的数据处理功能而言, 主要集中在存储和调用两个方面。那么, 基于计算机高级语言研发的数据库软件具有怎样的特点呢?

1.1 数据库软件的特点分析

数据库软件具有数据处理能力强、存储快捷、调用方便等诸多优点, 在目前的数据处理领域, 数据库软件是非常有价值的数据处理软件, 因为数据库软件的出现改变了对于数据处理的传统理解, 并且能够将处理效率最大限度地提高。此外, 由于数据库软件是基于计算机开发的, 针对计算机就可以对数据库进行进一步地开发, 例如加入声控或者数显扫描等功能, 从而让数据库软件的功能更加强大, 实现全面地智能化与人性化操作。

1.2 数据库软件的技术分析

数据库软件是基于计算机平台开发的数据处理功能软件, 其功能强大, 保证了数据处理的高效性和智能化。但是, 随着人们对于数据处理的要求逐步提升, 传统的数据库软件处理方式也出现了一定的改进和创新。在技术应用方面, 远程通信, 单片机的结合以及智能化方式都有了进一步的改善。总之, 对于数据库软件而言, 方便快捷地数据处理, 是未来的发展需求, 也是保证数据库软件能够持续应用的基本需求。

在智能化领域, 进行智能化存储, 以及智能化调用, 是未来进一步开发和设计的目标。通过目前的理论基础, 已经可以引入扫描以及声音录入的方式, 这两者均比较适合未来的数据库软件开发。在智能化的发展过程中, 数据库软件可利用声控和图像智能识别的方式, 来进行数据的存储和录入, 并进行声控的调用, 从而简化用户的操作, 实现智能化的数据库软件应用。

2 数据库程序开发的存储指令设计分析

计算机技术的发展, 为人们的生活和工作带来了巨大的变化, 传统的一些工作和生活方式因此不再适用于现代社会的发展。因此, 在现代社会中, 基于计算机技术的软件开发越来越普及, 数据库软件就是其中一款功能强大的软件。

对于数据库软件的存储指令设计而言, 需要进行怎样的技术研发呢?在未来的发展过程中, 又可以采用哪些智能化的方式, 使数据库软件的存储指令更加人性化呢?

2.1 分析数据库软件的存储指令设计原理

计算机技术的原理是将所有的内容数据化, 因此可以说计算机时代就是数据时代, 任何数据都可以进行相互的转换, 任何内容也都可以采用数据的形式呈现。那么, 数据库软件就有了技术原理的支持。

对于数据库软件中的存储指令设计而言, 一般的技术原理可以这样理解。

2.1.1 数据的存储原理

将内容以数据的方式进行录入, 占据虚拟的数据库软件空间, 就实现了初步录入和存储操作。可以针对数据的存储模式和存储需求, 对数据的保存时间进行设定。在一些大型的数据库软件中, 一般情况下数据都不是永久保存的, 尤其是一些网页类的数据库。在网页访问的过程中, 都会生成访问日志, 而访问日志的数据库就不会永久保存, 因为这样的数据没有长久保存的价值, 再者数据过多会造成数据库软件存储过载。因此, 存储既是为了数据的保存, 也是为了让数据更加有用。

2.1.2 数据的重叠与替代原理

如果相同的数据分别进行了存储, 数据库软件一般会分存储区进行存储;但是一个存储区内被相同的数据多次存储, 那么该存储区内将只保留最后一次录入的结果。因此, 在数据库软件进行数据存储的过程中, 一定要对指令进行相应的设定。对于数据的识别, 仅针对存储区域进行识别, 而不是对数据的等同性进行识别。这样的设计方式非常适合数据库的存储功能, 因为即使重复数据是相对普遍存在的, 其存储空间却是唯一的。

2.2 数据库软件的存储指令开发潜力探究

虽然目前的数据库软件存储功能已经非常强大, 对于内容的识别能力也具有一定智能性, 但是存在一个问题无法解决——如何将录入和存储直接连接, 从而保证录入的高效性。

由于传统的数据录入模式依然普遍采用手工方式, 非常消耗时间, 造成了工作效率低下等问题。因此, 数据库软件的操作过程依然具有非常巨大的潜力。例如, 可以实现智能化录入, 将人工录入方式转换成自动录入与存储方式, 从而减少了人工成本, 也提高了工作效率和准确性。

2.3 基于智能化理论的数据库存储指令开发分析

目前, 数据库软件的开发前景非常巨大。因为, 目前的存储过程更多是基于手工录入的方式, 存在较大的问题。第一是手工录入的工作量相对较大, 过程太复杂, 容易造成操作者的疲劳;第二是在使用过程中, 一旦操作者出现失误, 就会造成存储的数据出现错误, 影响整个数据库地正常使用。因此, 对于目前的数据库软件而言, 存储的效率和准确性需要提高。

基于智能化的技术理论, 以及目前计算机技术的发展水平, 完全可以引入扫描的方式进行存储。因为将数据数字化通常都是采用手工录入的模式实现存储。但是, 如果可以将数据库软件与扫描软件结合, 就可以利用扫描仪对传统数据进行扫描, 然后在数据库软件中设计相应的转换软件, 将扫描的结果直接录入, 从而降低存储操作的工作量, 并且可以实现智能化以及高效化相结合。

总之, 对于数据存储指令的设计, 首先要明确其研发的原理, 其次要通过良好的设计理念, 使其更加智能化和人性化, 才能保证存储指令更好地服务于使用者, 也让数据库软件更加智能化和高效化。

3 数据库程序开发的调用指令设计分析

对于数据库软件的调用指令, 应该如何进行合理设计, 才能保证调用的可行性并且提高工作效率呢?以下将进行详细分析。

3.1 数据库软件调用指令的原理分析

在数据库的设计过程中, 为了方便数据的查找, 在数据库软件中加入了调用语句。数据调用的方式非常高效和智能, 一般情况下是采用关键词或者关键词的方式进行调用。但是, 调用的前提是对数据进行存储。调用过程一般分为以下几个步骤。

3.1.1 输入关键词或者关键字

在定义关键词或者关键词的过程中, 一般都会进行数据提示或者设定。例如, 要查询一件衣服的价格, 就需要确定关键词, 一旦关键词确定就可以进行库内查找了。实际上, 查找的原理就是在库内进行文字匹配, 如果配对正确, 就可以通过调用语句, 将匹配正确的相关内容进行显示。这就是关键词或者关键词的调用方式。

3.1.2 数据调用匹配的原理分析

数据的匹配即是利用查找配对原理, 通过搜索功能, 将输入的关键词进行库内排重与查询, 一旦遇到匹配的内容就直接显示, 从而实现调用功能。

3.1.3 数据调用的显示原理

进行关键词或者关键词匹配之后, 利用调用语句, 将库内内容与关键词或者关键词进行匹配, 匹配后将与之关联的语句整体显示, 从而显示调用的语句。

3.2 数据库软件调用指令的智能化设计

目前数据库软件的调用功能非常强大, 但是操作的过程通常还是利用关键词或关键词进行查找, 而关键词或关键词通过操作者输入文字来获取。这方面还存在很大的发展空间, 比如, 如果可以使用声控的方式, 数据库软件的调用功能就会更加强大。因此, 加入声控的功能, 对于数据库软件的智能调用非常有价值。

4 结语

在使用数据库软件的过程中, 主要就是进行数据的存储以及调用, 两者在很大程度上决定了数据库软件的效率。虽然目前数据库软件的功能已经非常强大, 可以实现数据的任意存储以及调用, 但是依然存在很大的开发和设计空间。尤其是在智能化领域, 如何进行智能化存储, 以及智能化调用, 都需要进一步开发和设计。

通过目前的理论基础, 可以引入扫描以及声音录入的方式, 均比较适合未来的数据库软件开发方向。在智能化发展过程中, 数据库软件可利用声控和图像智能识别方式, 来存储和录入数据, 并进行声控的调用, 从而简化用户的操作, 实现智能化的数据库软件应用。

数据库调用 篇2

matlab存储变量在一块内存区域中,该区域成为基本工作空间。脚本文件和命令行创建的变量都存储在基本工作空间里面(workspace),函数不使用基本工作空间,每个函数都有自己的函数空间。

下面是函数与工作空间共享数据的方法:

1、使用global,将变量声明为全局变量

2、使用evalin和assignin(常用方法)evalin:在函数M文件中访问工作空间中的变量

[a1,a2,…] = evalin(ws,expression)说明:在工作空间ws中执行expression命令或表达式,并将执行的结果保存在变量[a1,a2]中 例:

v = evalin(’base’,’var’);%把基本工作空间中的变量var的值赋值给局部变量。

v = evalin(’base’,’var’);%查询基本工作空间中的变量名称

assignin:将函数M文件中的变量的值传给指定的工作空间中的变量

assignin(ws,’var’,val);说明:将变量val的值赋给工作空间ws中的变量var,如果变量var在工作空间中不存在,则创建该变量。例:

数据库调用 篇3

数据库的字段名通常是英文编码,在面对大量的数据表时,让数据库使用者记住每个编码的中文含义是比较困难的,更何况数据库使用者和设计者往往不是同一个人;但是若以中文作为字段名又不方便程序操作。Access数据库的字段有标题(Caption)属性很好兼顾了阅读性和操作习惯两方面的需求,在标题里添加中文则会在数据表显示时看到的是中文列标题,并且由于实际上字段名仍然是英文代码,所以也不影响程序控制。

问题在于手工添加字段标题费时费力且容易出错,所以迫切需要用程序程序批量向Access数据库中写入字段标题信息。

2 分析及思路

批量写Access字段标题问题可以分解为两个关键问题:

(1)程序操作——程序操作Access标题属性;

(2)批量——数据字典录入字段名和标题对照信息。

本应用的设计思路是将字段名和字段中文还有详细说明等信息存在一个数据字典中,遍历数据库每个字段并依次从字典中取出对应的字段中文信息,然后将该信息写入字段标题。

3 关键技术

对应上面的分析,首先不得不涉及到数据库访问技术,其次便是数据字典技术,下面简单介绍一下常见的数据库访问技术的演变历史和数据字典技术。

3.1 数据库访问技术简史

ODBC是Microsoft和Sybase、Digital于1992年共同制定的数据库访问标准接口,后获得广泛支持而逐渐成为标准的数据存取技术,不过ODBC仅支持关系数据库,以及传统的数据库数据类型。OLEDB是基于COM技术的一组接口规范,是系统级数据访问接口,OLEDB提供通用数据访问的方式,不管数据是以何种形式存储,可以对电子邮件、文本文件、复合文件、数据表等各种各样的数据通过统一的接口进行存取的一种技术。DAO是基于Microsoft Jet数据库引擎的面向对象的一个数据库访问接口,提出的初衷是让VB程序员访问Access数据库。DAO由于本身的特点,在访问Access时有很好的性能,但是在访问其他关系型数据库或者远程数据库时,仍然需要调用ODBC的API函数,所以微软综合了DAO和ODBC的优点提出了RAO数据库访问技术。ADO则是在整合了DAO和RAO的优点,基于OLEDB (ActiveX技术)技术设计的应用层数据访问接口,支持关系数据库和非关系数据库的访问。2000年微软将ADO的改进版ADO+纳入到.NET框架之下,再加上NET的类别库和程序语言一起组成了现在的ADO.NET。ADO NET是.NET框架的主要组成部分,是目前最流行的数据库访问技术。

ADO.NET是.NET环境下选择的数据库访问技术。ADO NET中两个数据库架构信息获方式OleDbDataReader GetSchemaTable () 和OleDbConnection.GetOleDbSchemaTable () 并不能获取到Access数据库的字段标题信息。DAO数据库访问技术却可以轻松获取,主要原因是由于DAO是基于Microsoft Jet数据库引擎,在访问Access数据库时有较好的性能。

3.2 数据字典技术

数据字典(Data Dictionary, DD)是关于数据库系统中各类数据的描述,是“关于数据库及其系统的数据库”,它包括的内容很多,如数据库结构的信息、数据库安全信息和其它内部表的信息等。伴随数据字典而产生的是数据字典技术,它是指与数据字典的建立和使用等相关的一套技术,它至少应包括数据字典和对之进行操纵的相关程序两部分内容。

本设计用到的数据字典itemdict仅为某地区地质灾害预警指挥系统《数据仓库及管理系统》项目的一部分,该字典记录的是与系统相关的所有的数据项的详细信息,其中本项目中主要用到的是编码和中文的对照信息。这里编码有统一编码field_name和内部编码field_code两种,如表1所示。

4 软件实现

4.1 设计思路

(1)遍历数据库所有字段。

(2)通过DAO技术访问Access数据库的字段属性,包括标题(Caption)。

(3)以字段编码(field_code或field_name)从itemdict字典中取出对应的中文(field_capt)信息。

(4)修改或创建标题信息。

4.2 软件实现

软件实现界面如图1所示,这里“目标数据库”选择操作对象数据库,“数据字典”选择含有字段编码和中文对照信息的数据字典,单选框选择写数据库字段标题或者说明。其中在选择字段组合框中有两个控件,下拉框和列表框。下拉框是用来选择表,这里将可能用到的表做了一个筛选,只留下可能包含这些信息的表如dict、tablereport或itemdict等所示;列表框中显示可能用到的字段如field_name或field_code,表示选择统一编码(field_name)或内部编码(field_code)作为取中文的凭证。

这里把选择数据库和选择字段做成通用可选参数,是为了满足用户对不同版本的数据字典的要求。因为不同的字典可能包含字段编码和中文等信息的表名和字段名不同,这里对表和字段进行筛选则是为了方便用户选择。

4.3 关键代码

通过DAO技术访问数据库字段标题属性,字段该属性项有初值则修改,无初值则创建新的标题属性。出错则写日志记录出错位置和原因。

5 结语

本设计用C#调用DAO操作Access数据库,通过数据字典技术批量写Access字段标题和说明,并把关键参数设置为可选,达到了预期的效果,如图2所示。

摘要:数据库字段名一般是英文编码, 需要对照中文才能理解。Access数据库字段标题很好地兼顾了数据库可读性与设计习惯, 但是标题信息的填写比较繁杂。讲解用Visual C#调用DAO并通过数据字典技术实现批量写入Access数据库字段标题和字段说明的应用。该应用对充分发挥Access数据库的可读性取得了很好的效果, 给数据库应用人员提供了极大的便利。

数据库调用 篇4

1、首先创建一个Objective-C的项目:

2.添加一个Swift的类文件:

3、点击Next,弹出一个对话框,选择YES

4、生成一个YourProject-Bridging-Header.h文件,

5、在SwiftClass创建类如下:

import Foundation class SwiftTest : NSObject { func test->NSString{ return “test” } }

6、在ViewController调用SwiftTest类如下:

#import “ViewController.h” #import “ObjectiveTest-Swift.h” //这里注意和项目名称一致 “YourProject-Swift.h”

7、import之后一定要先编译一次,否则编译出错,

Objectivec调用Swift

8、编译之后就可以在类里面调用了如下:

数据库调用 篇5

在Vfp中不是也能制作图表吗?也对也不对。对于图形来说我们可以通过'查询设计器来生成图形,但这样的图形看不中用,因为首先你无法打印,更无法生成一个图形文件供你随时查看修改,你每看一次必须用代码重新生成一次,对生成的图形的二次编辑等均无从谈起。报表也一样,Vfp提供了制作报表的功能,你可以把报表设计的很花哨,然而对于Vfp6.0而言,这种报表只能打印却不能传送给他人。比如你的上司要求你把报表,以文件的形式通过局域网发送给本单位的其他科室参考或进行修改,你总不能要求这十个部门都在微机上安装VFP6.0吧?

以上问题如果我们能在VFP中调用Excel电子表格就可以迎刃而解了。首先Excel共可生成30多种类型的图形,一次成图存盘后既可以随时调看修改图形,又可以把该图形文件作为邮件的附件通过网上传送给任何个人或部门。我们在Vfp中经过统计处理的数据(dbf文件)可以利用Excel生成报表,Excel的制表功能又是大大强过Vfp。举例来说,财务报表经常需要在表格里制作出斜线,Excel可以做得很轻松,而Vfp只能是望洋兴叹!接下来谈谈Vfp调用excel生成统计图形报表的问题,初学者可能以为这会是件很难的事情,其实还是很简单的。

我们从vfp调用excel生成图表的角度来简单了解一下excel中的一些基本概念:

Application对象:它在excel对象结构中处于顶层,形象地说,双击Excel快捷图标就相当于创建了一个Application对象;Workbooks对象:即工作簿对象(集),启动Excel后点击‘新建’或‘打开’快捷键就相当于创建或打开了一个Workbook;Worksheets对象:即工作表(集),启动Excel后工作表集会自动默认含有sheet1、sheet2和sheet3这三个工作表;Charts对象:图表(集),与Worksheets对象同级;Cells对象:表格(集),即我们看到的一个个格子;Range对象:是格子的一个范围,同Cells对象同级。

下面就“自卸车举升机构计算分析系统”在开发时,利用VFP控制Excel输出数据报表和生成图形曲线作一下介绍:

首先参照图1设置数据库表文件结构,运行自卸车举升机构计算分析系统,计算出了举升机构各点在不同举升角度下的坐标、受力的大小和方向以及油缸油压和行程等。

先来看范例数据表Zbk.dbf结构(如下列表),该数据库表包含了举升机构各点在不同的举升角度下的坐标。Gdslk.dbf该数据库表包含了举升机构各点在不同的举升角度下受力大小方向、油压、油缸行程及C点到车箱底板的距离等基本数据。

Zbk.dbf数据表结构

Gdslk.db数据表结构如下:

接着我们就来利用Vfp调用Excel电子表格生成各点坐标报表、各点的受力及液压缸的特性曲线图等。

生成各点坐标报表程序代码如下:

Vfp调用Excel电子表格生成各点受力及液压缸的特性等曲线图,本文仅以生成拉杆受力曲线为例,其他曲线与此相同仅需改变数据源和单位即可,编写代码如下:

以上程序代码编译后,在Windows2000/Windows XP

调用存储过程的通用方法 篇6

在VB.NET中存储过程分为有返回值的和无返回值的, 不论哪种存储过程, 它的调用方法都可以概括为下面的几步:

(1) 声明一个Sql Connection实例。

(2) 声明一个Sql Command实例, 并且设置其Connection属性为刚声明的Sql Connection实例, 设置Command Name为存储过程名, Command Type为存储过程。

(3) 向声明的Sql Command实例的Parameters集合中添加所有的存储过程调用需要的参数。

(4) 声明Sql Data Adapter和Data Set, 设置Sq Data Adapter的Select Command属性为2中声明的Sq Command实例, 再调用其Fill方法来把返回的行集填充到Data Set中。

(5) 关闭Sql Connection实例。

(6) 释放声明的各个实例。

调用不同的存储过程, 只是第二步的Command Name和第三步中的参数不同。

我们要写一个通用的调用存储过程的方法, 该方法只需要提供要调用的存储过程名字和提供具体的参数值就可实现任何存储过程的调用, 那么就要自动实现如何根据存储过程名来得到它所有的参数信息, 再根据这些参数信息自动创建各个参数。在每个SQL Server数据库中都有自己的系统表。这些系统表被用来保存配置和对象信息。从这些系统表中, 可以得到每个存储过程的所有参数的信息, 其中syscolumns表就保存了包括参数名、类型、长度、方向等需要用到的存储过程的信息。不过, 系统表中的字段会随着SQL Server版本的变化而变化。比如syscolumns中的type和xtype, 它们都保存了类型的信息。要让我们的方法适应SQL Server的版本变化要求, 就要用到信息结构视图。

ANSI-92将信息结构视图定义为一组提供系统数据的视图。利用该视图, 可以将实际系统表在应用程序中隐藏起来, 这样系统表的改变就不会影响到应用程序, 应用程序就可以独立于数据库厂家和版本。

ANSI-92和SQL Server支持用三段命名结构引用本地服务器上的对象。ANSI-92术语称为catalog schema.object, 而SQL Server称为database.owner object。例如, 要找到某个存储过程的所有参数信息, 就用:

那么如何编程实现通用的调用存储过程的方法呢?其部分程序如下:

首先定义两个类:一个是用来作为返回值的载体的, 用一个Data Set返回查询出的数据, 用一个Hashtable返回存储过程的返回值和输出参数;另一个类用来完成声明Sql Connection、Sql Command、Sq Parameter, 创建各个Sql Parameter的功能。

在VB.NET中常用的返回结果集的类为Sql Data Reader和Data Set, 而Sql Data Reader必须在保持连接的状态下才可以使用, Data Set却不需要。在本文的实现方法中, 连接应该在调用之后就断开, 因此采用Data Set来保存返回结果集。

这样用户只需提供存储过程的名字和各个参数值就可以调用存储过程。

摘要:在VB.NET中存储过程的调用模式几乎一样, 不同之处是每个存储过程的参数不同, 所以每调用一次存储过程重复代码很多, 这在做项目时很麻烦。笔者经过实践实现了在VB.NET中调用存储过程的简单方法, 该方法只需要提供要调用的存储过程名字和提供具体的参数值就可实现任何存储过程的调用。

C#调用动态链接探析 篇7

从Windows操作系统诞生之日起, 就使用动态链接库 (DLL) 来支持公共函数的调用, 区别于在编译时发生、直接把代码插入到程序EXE文件的静态链接。动态链接是指程序运行时才把自己需要的函数链接进来的代码调用方式, 也就是说只要在应用程序需要时, 才加载DLL到进程的虚拟空间, 成为调用进程的一部分。程序使用DLL的优点包括:一方面, 可以减少在磁盘和物理内存中加载的代码的重复量;另一方面, 也可以促进模块式程序开发和简化程序部署和安装。每种编程语言调用DLL的方法都不尽相同, 本文对用C#调用DLL的方法进行介绍。

1动态链接库 (DLL) 的基本分类

每种编程语言调用DLL的方法都不尽相同, 本文只对用C#调用DLL的方法进行分析总结。首先, 需要了解什么是托管, 什么是非托管。随着.net平台的引入, 代码分为托管代码和非托管代码, 托管代码由公共语言运行库环境 (而不是直接由操作系统) 执行的代码。托管代码应用程序可以获得公共语言运行库服务, 例如自动垃圾回收、运行库类型检查和安全支持等。这些服务帮助提供独立于平台和语言的、统一的托管代码应用程序行为。非托管代码指在公共语言运行库环境的外部, 由操作系统直接执行的代码。非托管代码必须提供自己的垃圾回收、类型检查、安全支持等服务;它与托管代码不同, 后者从公共语言运行库中获得这些服务。对于动态链接库DLL来说也分为托管的DLL和非托管的DLL。

2非托管的DLL的C#调用

2.1对于不是基于com的非托管的DLL访问

首先, 应该在C#语言源程序中声明外部方法, 其基本形式是:

[DLLImport (“DLL文件”) ] //-访问DLL文件

修饰符 ReturnType FunctionName (type arg1, type arg2, ...) ;//--声明方法。

其中:DLL文件是包含定义外部方法的库文件。修饰符是除了abstract以外在声明方法时可以使用的修饰符, 一般为public static extern。返回变量类型是在DLL文件中需调用方法的返回变量类型。方法名称是在DLL文件中需调用方法的名称。参数列表是在DLL文件中需调用方法的列表。DllImport还包含了一些可选属性, 其中4个比较常用:

(1) EntryPoint 参数给出 DLL 中入口点的名称。如果未指定 EntryPoint, 则使用方法本身的名称。

(2) CharSet 参数指示用在入口点中的字符集。如果未指定 CharSet, 则使用默认值 CharSet.Auto。

(3) SetLastError 参数指示方法是否保留 Win32“上一错误”。如果未指定 SetLastError, 则使用默认值 false。

(4) CallingConvention 参数指示入口点的调用约定。如果未指定 CallingConvention, 则使用默认值 CallingConvention.Winapi。

在使用DllImpor时记得引用所在的命名空间System.Runtime.InteropServices, 同时对于不同类型实现的DLL引用的方法也不尽相同。

2.1.1 引用普通winapi中的方法和自己编写的类库中的普通函数方法

采用DllImport的方法直接导入, 如要调用Winapi中的MessageBoxA功能可以:

[DllImport ("user32.dll", EntryPoint="MessageBoxA") ]

static extern int MsgBox (int hWnd, string msg, string caption, int type)

其它参数采用默认值。如果是自己编写的DLL文件中的函数, 一要注意DLL文件所在的位置, 可以放在项目文件夹下的../bin/Debug/目录里或者放在系统目录C:/Windows/system32里;二要注意DLL文件中使用的参数调用方式。C和C++缺省调用方式是_cdecl?, 而系统默认的方式是CallingConvention.Winapi要改为CallingConvention.Cdecl。

2.1.2 引用类库中类的方法和属性

一种是要在C#中调用类库中类的方法, 通过静态方法导出C++中的方法, 在C#中创建同名的类来接受C++中静态的方法, 注意此时C++类中的方法编译后名称改变, 通过dumpbin命令来查看编译后的名称并进行映射;另一种是要在C#中调用类库中类的属性, 主要使用System.Runtime.InteropServices命名空间的Marshal 类的PtrToStructure方法实现DLL中类的创建, 通过创建的类来实现属性的访问。

2.2对于基于COM的非托管DLL的访问

对于非托管代码下基于COM的DLL, 可以先用tlbimp命令将COM类型中定义转换为公共运行时的等效定义。如:TlbImp test.dll /out: test_clr.dll, 在直接在C#项目中添加对test_clr.dll的引用。然后倒入对应的命名空间, 即可访问COM库的类中方法。如果使用 Visual Studio 开发环境, 则只需添加对COM类型库的引用, VS将为您自动完成此转换。

上面使用的TlbImp.exe (类型库导入程序) , 它是一个包括在 .NET 框架 SDK 中的命令行工具。TlbImp 将 COM 类型库转换为 .NET 框架元数据, 从而有效地创建一个可以从任何托管语言调用的托管包装。用 TlbImp 创建的 .NET 框架元数据可以通过 /R 编译器选项包括在 C# 内部版本中。

注意:在最新的VS2010中直接添加对COM类型库的引用并自动完成此转换后, 要修改DLL的文件引用属性的“嵌入式操作类型”, 由默认的true修改为false, 否则提示无法嵌入互操作类的错误。而在vs2005和vs2008中并无引用属性“嵌入式操作类型”。

3托管的DLL的C#调用

C# 调用托管DLL是很简单的, 只要在“解决方案资源管理器”中的需要调用DLL的项目下用鼠标右击“引用”, 并选择“添加引用”, 然后选择已列出的DLL或通过浏览来选择DLL文件, 最后需要用using 导入相关的命名空间。需要注意的问题也是vs2010中DLL文件引用属性的“嵌入式操作类型”, 也需要由默认的true修改为false。

3.1动态调用托管DLL

C# 动态调用托管DLL也需要借助System.Reflection.Assembly里的类和方法, 主要使用了Assembly.LoadFrom。假如在托管代码的命名空间Test中的Class1类中有Method方法, Method方法有一个int类型参数并返回int的值, 就是假设Method起一个简单的数据处理和返回的作用。编译生成托管的Test.dll文件。在C#项目中要动态引用该DLL, 先导入命名空间:using System.Reflection;在主函数中的调用代码大致如下:

4结语

使用DLL有很多优点, 如:节省内存和减少交换操作;开发大型程序时可以把某些模块分配给程序员, 程序员可以用任何一门所熟悉的语言把该模块编译成DLL文件, 这样可以提高代码的复用, 大大减轻程序员的工作量。所以, 如何灵活地调用DLL应该是每位程序员所熟知的。

本文重点对DLL进行了详细的分类, 对C#访问DLL的方法进行了综合和分析, 提出了调用中要注意的问题。笔者已经在多个项目中使用了上述的访问技术, 提高了工作效率, 缩短了研发周期。

参考文献

[1]潘爱民.COM原理与应用[M].北京:清华大学出版社, 2010.

[2]王小科.C#开发实战宝典[M].北京:清华大学出版社, 2010.

[3]郭新苍, 樊来耀.NET互操作技术研究[J].无线电工程, 2009 (6) .

浅析Linux的系统调用方法 篇8

系统调用是操作系统为用户态的进程与硬件设备 (如CPU、磁盘、打印机等) 之间的交互提供的一组接口。其主要目的是使得用户可以使用操作系统提供的有关设备管理、文件系统、进程控制、进程通讯以及存储管理等方面的功能, 而不必了解系统程序的内部结构和有关硬件细节, 从而起到减轻用户负担和保护系统以及提高资源利用率的作用。以下以Linux系统体系结构为例 (图1) , 分析系统调用的意义。

Linux系统分为三个层次:用户、核心以及硬件。其中系统调用是用户程序与核心间的边界, 通过系统调用进程可由用户模式转入核心模式, 在核心模式下完成一定的服务请求后再返回用户模式。系统调用可以看作是一个所有Linux进程共享的子程序库, 是由内核提供的、功能十分强大的一系列函数。它们在内核中实现, 可以存取核心数据结构和它所支持的用户级数据, 然后通过一定的方式呈现给用户。

2 Linux内核对系统调用的管理

2.1 与系统调用有关的数据结构

为了实现系统调用功能, Linux在内部定义了相关的数据结构。

2.1.1 系统调用响应函数名的约定

函数名以“sys_”开头, 后跟该系统调用的名字, 由此构成238个形如sys_name () 的函数名。例如fork () 的响应函数是sys_fork () 。

2.1.2 系统调用号

通过系统调用号可以找到系统调用表 (sys_call_table) 中对应表项的内容, 它正好就是该系统调用响应函数的入口地址。文件/usr/src/linux-2.4.18-3/include/asm-i386/unistd.h为每个系统调用分配一个唯一的号码。文件中每一行的格式如下:#define __NR_name NNN。其中, name用系统调用名称代替, 而NNN则是该系统调用对应的号码。文件内容如下所示:

#define __NR_exit 1

……

#define __NR_tkill 238

2.1.3 最大系统调用数

在/usr/src/linux-2.4.18-3/include/linux/sys.h中定义的NR_syscalls表示该表能容纳的最大系统调用数, #define NR_syscalls = 256。

2.1.4 系统调用表

系统调用表记录了各个系统调用处理函数的入口地址。通过这张表就可以根据特定系统调用在表中的偏移量, 找到对应的系统调用响应函数的入口地址。系统调用表在文件/usr/src/linux-2.4.18-3/arch/i386/kernel/entry.S中定义, 其中“.”代表当前地址, sys_call_table代表数组首地址, NR_syscalls为系统调用总数。其结构如下所示:

该清单用来对sys_call_table[]数组进行初始化。该数组包含指向内核中每个系统调用的指针。

2.2 系统调用中参数的传递

为使系统调用的执行成为一项简单的任务, Linux提供了一组预处理宏指令, 它们可以用在程序中。这些宏指令取一定的参数, 然后扩展为调用指定的系统调用的函数。在/usr/src/linux-2.4.18-3/include/asm-i386/unistd.h这个头文件中不仅定义了所有的系统调用号, 同时还定义了7个与系统调用有关的宏, 即_syscallN () , N取0~6之间任意数。这些宏用于系统调用的格式转换和参数的传递。

这些宏指令具有类似下面的名称格式:

_syscallN (parameters)

其中N是系统调用所需的参数数目, 而parameters则用一组参数代替。这些参数使宏指令完成适合于特定的系统调用的扩展。例如, 为了建立调用setuid () 系统调用的函数, 应该使用:_syscall (int, setuid, uid_t, uid) 。

_syscallN () 宏指令的第一个参数int说明产生的函数的返回值的类型是整型, 第2个参数setuid说明产生的函数的名称, 后面是系统调用所需要的每个参数, 这一宏指令后面还有两个参数uid_t和uid分别用来指定参数的类型和名称。

另外, 用作系统调用的参数的数据类型有一个限制, 它们的容量不能超过四个字节。这是因为执行int $0x80指令进行系统调用时, 所有的参数值都存在32位的CPU寄存器中。使用CPU寄存器传递参数带来的另一个限制是可以传送给系统调用的数目。这个限制是最多可以传递6个参数。所以Linux一共定义了7个不同的_syscallN () 宏指令, 从_syscall0 () 、_syscall1 () 直到_syscall6 () 。

一旦_syscallN () 宏指令用特定系统调用的相应参数进行了扩展, 得到的结果是一个与系统调用同名的函数, 它可以在用户程序中执行这一系统调用。

2.3 系统调用过程

系统调用的过程如图2所示。其中粗线表示控制流, 细线表示相关数据关系。

(1) 虚框内, 系统处于用户态。用户程序请求系统服务时, 要以C语言函数的形式写一条系统调用命令。假如该命令已在某个.h文件中由相应的_syscallN () 展开, 则用户程序必须include该.h文件。

(2) _syscallN () :当程序执行到此调用时, 实质上是在执行由宏_syscallN () 展开的函数, 它将系统服务请求转换为中断。系统调用的参数由各通用寄存器传递。

(3) 系统执行int $0x80后, 以核心态进入入口地址system_call (代码在entry.S中) 。从system_call入口的汇编程序, 主要执行如下功能:保存寄存器当前值 (SAVE_ALL) ;检验调用是否合法;根据系统调用表sys_call_table[]和寄存器EAX中的系统调用号找到相应的系统调用响应函数并转入执行。当响应函数执行完毕后, 让EAX寄存器保存函数的返回值。这时, 控制转到ret_from_sys_call。

(4) ret_from_sys_call负责恢复现场信息, 将机器从内核态切入到用户态, 继续执行中断的程序。

3 在Linux中添加新的系统调用

添加新的系统调用可以通过两种方式实现, 一是通过修改内核源代码, 二是利用Linux内核模块。通过修改内核源代码的方式, 将新的系统调用直接静态编译成内核的一部分, 这样会增加内核的大小, 还要改动内核的源文件, 而且不能动态地卸载, 不利于调试;利用Linux内核模块的方式, 则是将新的系统调用编译成可以动态加载的模块, 所以推荐使用模块方式。

3.1 通过修改内核源代码添加系统调用

用户在Linux中添加新的系统调用, 可以遵循几个步骤才能添加成功, 下面几个步骤详细说明了添加系统调用的相关内容。

3.1.1 添加源代码

第一个任务是编写加到内核中的源程序, 即将要加到一个内核文件中的函数, 该函数的名称应该是新的系统调用名称前面加上sys_标志。假设新加的系统调用为mycall () , 在/usr/src/linux-2.4.18-3/kernel/sys.c) 文件中添加源代码 (作为一个最简单的例子, 新加的系统调用仅仅返回一个整型值) , 如下所示:

3.1.2 连接新的系统调用

添加新的系统调用后, 下一个任务是使Linux内核的其余部分知道该程序的存在。为了从已有的内核程序中增加到新的函数的连接, 需要编辑两个文件。

第一个要修改的文件是/usr/src/linux-2.4.18-3/include/asm-i386/unistd.h。根据unistd.h文件查看Linux内核自身的系统调用号码已经用到238, 而sys.h文件中显示最大系统调用号为256, 因此新的系统调用号可在239~256之间, 可设定为:#define __NR_mycall 239。

第二个要修改的文件是:/usr/src/linux/arch/i386/kernel/entry.S。在相应位置添加.long SYMBOL_NAME (sys_mycall) , 这样就在sys_call_table[]数组中增加了新的内核函数的指针。

3.1.3 编译内核, 重启动系统

通过编译内核, 重建新的Linux内核, 让新添加的系统调用成为操作系统的一部分。然后用新内核启动系统, 这样用户就可以在应用程序中使用该系统调用了。

3.1.4 使用新的系统调用

与新的内核模块运行于内核态不同, 调用新的系统调用是在用户进程中进行并运行于用户态的。相应的, 调用新的系统调用所在的程序段只需在用户态下编译即可生成可执行文件。在应用程序中使用新添加的系统调用mycall。同样为实验的目的, 写了一个简单的例子exam.c。

3.2 利用Linux内核模块添加系统调用

3.2.1 编写内核模块

编写新的内核模块有比较固定的格式, 对应的具体程序段由以下三部分组成。第一部分是新的内核函数, 这个函数体中的代码明确了添加到内核中的模块所能完成的功能。第二部分是模块初始化函数 (init_module () ) , 主要用于初始化参数、系统注册、修改系统调用表等。第三部分是卸载模块时所调用的函数 (cleanup_module () ) , 这个函数将恢复初始化函数中修改的内容, 如卸除系统注册、恢复系统调用表等。

以下给出一个内核模块的编写实例 (mker.c) , 这个实例的组成如上所述。mker.c源程序内容如下。

3.2.2 编译新的内核模块

编写新的内核模块之后, 要对这个源文件进行编译。内核模块的编译需要用到一些选项, 以指明用哪种方式编译、最终的代码运行于哪种模式下等。具体操作为, 在命令行下键入gcc –Wall –DCONFIG_KERNELD –DMODULE –D_KERNEL_-DLinux –c mker.c。其中, –Wall选项是要求gcc将所有的警告信息显示出来;后面几个以D开头的选项则指明了编译出的代码运行在内核模式下。注意, 以这种方式编译出的不是可执行文件, 而是二进制模块文件mker.o。

3.2.3 加载和卸载新的内核模块

得到mker.o文件之后, 就可以将模块加载到内核中, 以供用户通过系统调用的形式调用该模块所加载的函数。可使用insmod命令手工把它加载到核心 (即在命令行键入insmod mker.o) 。insmod命令在/lib/modules/kernel-version目录的modules.dep文件里找到它要加载的被请求的核心模块, 然后进行加载。在模块被加载之后, 可以用命令lsmod列出所有加载的核心模块和它们之间的依赖关系, 以检查是否所需模块已加载在内核中。

当内核中的模块不再使用时就需要对其卸载, 以免它占用内存空间。模块可以用rmmod命令卸载 (即在命令行输入rmmod mker, 注意这里不带.o后缀) 。

3.2.4 使用系统调用

在编写好新的内核模块、将它加载到内核, 并且做好了新的系统调用之后, 我们就可以对这个新的系统调用在用户进程中进行具体的调用。以下为使用新添加的系统调用的程序段 (callsys.c) , 这个程序调用mycall () 函数来计算值, 并在终端输出。

3.2.5 系统调用工作流程

结合以上例子, 可将系统调用的工作流程总结如下:

当程序调用mycall () 这个函数时, 便会调用第三行, 通过查看头文件unistd.h中宏syscall2的定义, mycall () 会被展开成以下代码:

从中可以看出, 程序通过调用宏__NR_mycall得到调用号, 放到寄存器eax中, 同时将参数num1、num2放入通用寄存器ebx、ecx中, 接着执行中断指令“int $0x80”。这样就陷入到内核中, 根据系统调用号索引sys_call_table, 并找到最终的内核函数sys_mycall () , 这个内核系统调用函数仅返回计算得到的值, 将返回值送入CPU的eax寄存器中, 最后进程返回到用户态, 用户程序最终执行完成, 整个系统调用过程也就完成。

3.3 两种方式对比

通过修改内核源代码的方式, 将新的系统调用直接静态编译成内核的一部分, 这样会增加内核的大小, 还要改动内核的源文件, 而且不能动态地卸载, 不利于调试。

而利用Linux内核模块的方式, 则是将新的系统调用编译成可以动态加载的模块, 使用非常灵活, 所以推荐使用模块方式。

4 总结

综上所述, 由于Linux操作系统的自由开放性及容纳用户自定义系统调用的特性, 我们完全可以在原有系统调用的基础上, 添加一些有益的、实用的新的系统调用功能, 让Linux操作系统为我们提供更多更好的服务。

摘要:系统调用是连接应用程序和系统内核的关系纽带, 本文以RedHat Linux2.4.18为例, 通过对Linux操作系统中系统调用数据结构、参数传递、调用过程的分析, 提出了两种实现系统调用的方式, 并提供了详细代码。

关键词:Linux操作系统,系统调用,内核模块

参考文献

[1]陈莉君, 康华.Linux操作系统原理与应用.北京:清华大学出版社, 2006:133-148.

[2]陈刚, 卢显良.基于Linux-2.6内核模块程序设计.福建电脑, 2004, (6) :15-16.

数据库调用 篇9

(1)句柄。句柄是Windows系统用来标识对象的唯一整数,许多API函数需要句柄作为参数。通常,句柄用小写“h”开头,如hWnd表示窗口句柄,hDC表示设备场景句柄。在PB中,可以通过其handle函数来取得窗口或控件的句柄,当声明API函数时,常把句柄变量声明为Long或uLong长整型数据类型。

(2)设备场景。设备场景(DC)是一组由Windows系统定义的数据结构对象,结构对象定义了与绘图有关的一组图形和属性。在Windows系统中有四类DC,分别是显示、打印、内存和信息。DC是一种虚拟对象,PB不能直接获得,只能通过使用GetDC外部函数取得,比如,想要获取指定窗口的DC,须利用PB内部函数handle取得窗口的句柄hWnd,并将窗口句柄hWnd作为参数传给外部函数GetDC。需要注意的是,如果调用了GetDC函数,当操作指令结束后,需调用ReleaseDC API函数来释放内存资源。

2 PB API函数的语法格式

在PB中使用API外部函数之前,须首先进行声明。用户可以用两种方式来声明API函数。

(1)全局级API函数。可在应用程序的任意位置调用。

(2)对象级API函数。只能在窗口、菜单、用户对象等对象的内部调用。

外部函数的声明以两个关键字FUNCTION或SUB-ROUTINE为起始。如果函数所表达的过程有返回值,则应将其声明为FUNCTION,其语法如下:

如果函数表达的过程无返回值,则应将其声明为SUB-ROUTINE,其语法为:

在PB的声明中,大括号中的内容是可选的。声明中的其它各关键字作用如下:

Access:函数的访问级别,默认为Public,此参数只能在对象级外部函数中使用。

ReturnDataType:函数的返回值的数据类型,须与PB所支持的数据类型相匹配。

Functioname/Subroutinename:函数或过程的名称。名称可以由用户自定义,但如果与动态库内部函数名称不一致,则必须通过Alias For子句给出动态库中函数或过程的真正名称。

REF:标明变量通过引用方式传递。DataType:外部函数中参数的数据类型。Arg:外部函数的参数名。LibName:所要引用的动态库DLL或EXE的文件名。Externa|Name:表示DLL库中的外部函数或子程序名。

3 C数据类型与PB数据类型的转换

在MSDN中,API函数均为C语言格式,其数据类型也是完全按照C语言的格式进行定义的,这些数据类型与PB的使用格式存在一定的差异,需要进行转换。表1列出了API函数的C原型与PB相应数据类型的关系。

4 PB与API函数之间的参数传递

调用Windows系统动态库的函数时,大部分函数需要传入一个或多个参数。参数的传递方式可以是值传,也可以是引用传递。默认情况下,PB调用DLL中的函数是通过传值方式来进行的,也就是说PB将对要传递的参数做一份复制,然后通过堆栈将这份复制传递给外部函数,外部函数对其参数的任何修改不会影响到PB参数的原值。如果希望DLL中的函数来改变调用参数的原值,可通过引用方式来传递参数,即在参数数据类型前面加REF关键字来声明。通过引用方式传递参数,外部函数得到指向其参数的指针,外部函数可对其参数的值进行修改,并将修改后的结果回传PB中。需注意的是,在声明PB外部函数时,是否加关键字TRF,须根据MSDN对函数的定义,而不能随意添加。

5 PB调用API应注意的事项

(1)确保函数参数的正确性。在Windows环境中,16位和32位数据变量都可能按32位传递,当这些数据同时使用时很难发现其中的错误。

(2)有些API函数对大小写敏感。虽然PowerScript对大小写不敏感,但API函数却例外,比如,“FindWindowA”能正常工作,而“Findwindowa”可能会报错。

(3)合理分配全局级API函数与对象级API函数。虽然全局级API函数可以在程序的任意位置调用,但其占用的资源较多。应根据程序开发的最低需要,尽可能把API函数声明在对象级。另外,应及时释放使用过的内存资源,防止因申请内存资源失败而死机。

参考文献

[1]马贵安,李明武,牛永生.PowerBuilder Win32API函数调用参考手册[M].北京:清华大学出版社,2004.

[2]PB API调用原型.PB技术.http://www.procedurelife.com/techn-ical/PB/content/lebdl.html.

上一篇:学习评价模式下一篇:新型玻璃