VB VC混合编程疑难问题解
时间:2009-6-2 10:27:47 作者: 来源:
 

  我们在编写visualbasic应用程序的时候常常需要自己动手编写一些库函数或activex控件,而这些函数或者控件常常采用vc 语言来写,因而也常为vb和vc两种语言之间不同参数类型、内存空间使用方法等问题为难,怎么做好呢?本文介绍了在vb和vc混合编程的情况下对这些问题的解决方法。

  一、自定义类型参数向dll库函数的传递

  用vb,vc 进行混合编程时,通常需要在vb中调用vc 编写的dll库函数,这时,一般都要遇到向库函数传递参数的问题。对于标准类型(如double,long等)参数,其传递比较简单,只要保证了vb中对库函数的声明和vc 中对库函数的定义在参数类型、次序和传递方式上的一致性,参数就不会被错误传递。但是,如果需要向库函数传递自定义类型的参数,情况就会变得复杂了。

  情况一:自定义类型的所有成员变量都是同一种类型(例如下面的pens自定义类型,其成员都为long型)。
typepens
 redpennumaslong
 greenpennumaslong
 b1uepennumaslong
endtype
  这时,只要在vb和vc 中对该结构采用相同的定义,并充分注意到vb和vc 对某些数据类型(如32,位操作系统下,vc 中的int和vb中的integer)存储上的差异,就不会发生参数传递错误。

  情况二:自定义类型中成员变量的类型不完全一致。这时,又要区分两种情况:

  情况(1)没有double型成员变量。

  这时一般也不会出现参数的传递错误。

  情况(2)含有double型成员变量。

  这时参数通常就会被误传。比如传递下面的person类型的参数到vc 开发的dll库函数,double型成员height的值就会在传递中丢失:
typeperson
ageaslong
heightasdouble
endtype
  造成height值丢失的原因是由于在vc 中存储person型变量时,将自动在long型成员age和double型成员height之间插入若干字节的分隔空间,而vb则不会。所以,vc 中存储一个person型变量需要的内存要多于12字节,而vb只需要12个。因此,从vb传入dll库函数的person型变量就不能被正确接收。

  解决这一问题的方法有多种,这里介绍一种比较简便和普适的,称之为“引入补位成员法”:在person这种自定义类型中引入若干个内存补位成员,使得任一个double型成员之前的所有成员占用的字节总数都是单个double型变量所占字节数的整数倍(8的整数倍)。

  仍以person类型为例,由于age成员占用4字节内存,所以要在其后引入一个占用4字节的补位成员,不妨引入一个string型的成员tempst:
typeperson
 ageaslong
 tempstasstring*4
 heightasdouble
endtype
  于是,double型成员height之前的所有成员占用的内存总数变成了8个字节,是8的整数倍。此时,将dll库函数中对person的定义作同样的修改后,就可以正确接收从vb传来的person型参数了。

  注意:引入补位成员时,不但要合理分配其占用的字节数,而且要正确安排其在结构体中的位置,二者缺一不可。上例中,若把补位成员放在height之后,doubl型变量height之前的所有成员占用的字节总数仍然是4,不是8的整数倍。

  在自己编写dll库函数时,往往会在函数接口处使用复杂的自定义结构。在vb中调用这种函数时,采用“引入补位成员法”适当修改结构体的定义,就可以有效地避免参数传递上的错误。

  二、使用在vc 中动态申请的内存

  混合语言编程时,有时需要在vb代码中使用通过vc 动态申请到的内存。这时,可以通过下述方法实现:

  1)vc 中申请动态内存的dll库函数
char*apientrycreatestringbuffer(longlength)
{
char*bufv;//假设需要申请用以存放字符申的动态内存
buf=(char*)::malloc(length);
returnbuf;//返回字符串指针,其实就是一个long型数
}
  2)vb中接收动态内存指针的代码
......
declarefunctioncreatestringbufferlib"c:\dlltest\test.dll"_
(byvallengthaslong)aslong
'long型变t接收动态内存指针
......
dimslbuffer&
atbuffer=createstringbuffer(20)
'申请一块可存放20个字符的内存,得到指向该内存的指针
......
'使用该动态内存
......
  注意:vb中使用完动态内存后,为了避免内存泄漏二要将其指针传回vc 进行内存释放工作。

  三、自定义类型参数向activex控件的传递

  在编写vb程序时,如果使用的是标准activex控件,那么一般不需要向控件传递自定义类型的参数,因为大多数控件的大多数属性都是标准类型(如double,long)的。但是,在混合语言编程中,当我们采用vc 中的atl3.0模板(而不是vb)自行开发activex控件时,往往希望能够向控件的某些属性或方法传递自定义类型的参数,以提高参数的传递效率。

  这里介绍一种向控件传递自定义类型参数的简便方法。假设要以vb为客户端开发一个activex控件ax,它有一个student属性,类型是自定义结构person:
typeperson
 ageaslong
 heightasdouble
endtype
  第一,正确编写student属性的接口函数(以用atl3.0模板开发ax为例)。我们将student属性存取函数的接口参数类型写成一个long型的指针,而不再是bstr。因为activex内部的通信全部基于unicode基础之上,所以,这样处理会避免由于字符集不匹配而造成的参数误传。相关的代码如下:

  1)ax.idl中对student属性的定义
[propget,id(0),helpstring("propertystudent")]hresult
student([out,retval]long*pval);
[propput,id(0),helpstring("propertystudent")]hresult
student([in]longnewval);
  2)ax.h中对student属性存取函数的定义
stdmethod(get_student)(/*[out,retval]*/long*pval);
stdmethod(put_student)(/*[in]*/longnewval);
  3)axcpp中对student属性存取函数的实现
stdmethodimpcax::get_student(long*pval)
{
//todd:addyourimplementationcodehere
//得到存储student属性的成员变t的指针,赋给*pval
returns_ok;
}
stdmethodimpcax::put_student(longnewval)
{
//todd:addyourimplementationcodehere
//将存储student属性的成员变址的指针指向newval所指的内存空间,
//然后通过内存拷贝方式拷贝此空间存放的student的属性值
returns_ok;
}
  第二,正确编写vb向ax的student属性动态赋值的代码。在vb中,先声明一个person型变量,给该变量赋值后,获取该变量的内存地址并赋给student属性即可。代码如下:
......
dimstudentpropasperson
dimstudentaddraslong
studentprop.age=23
studentprop.heigth=1.78
'得到studentprop变量的内存地址(方法从略),赋给studentaddr
ax1.student=studentaddr
......
  借助指针完成自定义类型参数向activex控件的传递所依据的是以下事实:不论控件是.dll还是.ocx,它都是与其客户同在一个进程内的服务器。所以,只要ax被编译成.dll或.ocx,指针的传递就是安全可靠的。

  四、中英文混合型字符串输出长度的确定

  中英文混合型字符串输出长度的确定问题在vb编程中经常遇到,而且可以通过vb,vc 混合编程有效解决,所以在此一并给出。

  vb编程中,经常需要得到某个字符串在实际输出时所需要的长度。这时,我们通常会考虑len()和lenb()这两个函数。

  我们知道,len()返回的是字符串中字符的个数,对于不含中文字符的字符串,其返回值通常就等于该字符串的输出长度;lenb()返回的则是按照双字节字符集(dbcs)计算出的字符串所占用的字节数,对于纯中文字符组成的字符串,其返回值通常也等于该字符串的输出长度。但是,当字符串中既有中文又有英文(这里将数字等视为英文)字符时,二者的返回值都不等于该字符串的输出长度。比如:“a中国人”这个字符串,用len()函数时将返回4;lenb()则返回8;而实际输出时(比如向某记录文件输出该字符串),它将占用7个印刷符(每个英文字符占1个,每个中文字符占2个)。

  为了计算中英文混合型字符串的输出长度,我们可以用vc 编写一个完成此计算的dll库函数,在vb中直接调用该函数即可。该vc 函数和vb中的调用代码如下:

  1)vc 6.0中的dll函数
longapientrysizeof_vbstring(char*at)
{
return(long)(::atrlen(st));
//::atrlen()返回int值,但在32位操作系统下,
//vc 中的int类型与vb中long类型的范围是相当的
}
  2)vb6.0中对sizeof_vbstring()的声明和调用
......
declarefunctionsizeof_vbstringlib"c:\dlltest.dll"_
(byvalstasstring)aslong
......
......
dimstlen&
stlen=sizeof_vbstring("a中国人")
stlen=7
......
  应该指出:上述方法同样可以计算纯英文或纯中文字符串的输入长度。

->


上一篇:
下一篇:
 
网页模板 网站模板 网站建设 网页设计 网页设计师兼职 自助建站 ...
网站魔坊,网页模板,网站模板,免费网页模板,在线模板设计,免费建站,门户网站搭建,建站,企业网站,奇思网络,奇思,智能建站,自助建站,拖动建站,网站建设,网页设计,在线设计模板
www.wzmof.com/ 47K 2009-5-21
 
商巢...
商巢是一个真实的商业交友社区、为用户提供交友、贸易、社区、建站等服务;临渊慕鱼,不如退而结网!商巢结网行动
www.ncooo.com/ 47K 2009-5-21
 
商巢创业 门户创业 商人网络家园 魔坊建站 商业交友
商巢下的门户,门户又一独立实体与商巢合作,由商巢负责技术的更新以及硬件的支持,门户负责自己领域的市场推广以及相应的售后服务即可。 打破以往门户需要源源不断的技术、硬件投入模式,盈利模式清晰 行业门户以及门户下企业网站由网站魔坊...
mhcy.ncooo.com/ 36K 2009-5-14
 
奇思网络技术 网站建设 深圳网站建设
中小外贸企业做电子商务,需要从两点技术突围 08-01 企业网站建设 提供网站策划、网站建设、数据库开发至网络营销全套解决方案。能针对客户所处行业,结合营销特征量身订做高质量网站建设方案。 网站推广 怎样使网站的投资得到回报?这需要经验...
www.qsnet.com.cn/ 48K 2009-4-2
 
深圳艺术网
深圳艺术网,中国艺术网,中国当代艺术网,广东当代艺术网,广东艺术网,南方当代艺术网,深圳美术网,深港美术网,深港艺术网,深港当代艺术网,杜应红,深圳当代艺术创作库,深圳创库,深圳美术,深圳艺术,深圳收藏,深圳艺术收藏,深圳音乐网,深圳舞蹈...
www.szarts.cn/ 119K 2009-6-9
 
网页设计也通过人脉赚钱-技术传播
 
网页设计114 -打造中国网页设计、网站建设技术信息学习、交流、互动平台
                         打造网页设计师兼职创业平台中心