VC可否编出返回VB6中vc byte 转stringg类型的函数

1859人阅读
随笔_技术(7)
VC++(28)
VB中,应注意以下几点:
声明DLL函数时,有返回值的声明为Function,无返回值声明为Sub,参数类型要一一对应,注意参数类型的字节数;
注意AddressOf运算符用法;
VC中,应注意以下几点:
DLL输出函数应声明成&__stdcall&
声明回调函数指针时,注意&__stdcall&声明,示例:VB:Sub ShowData(ByVal nData As Long)VC:typedef VOID (__stdcall *FunPtr_VBCallback)(INT32)因为这一点,VC函数调用该回调函数之后,VB IDE老是崩溃
vc写dll,我只会写int类型的函数:__stdcall int CALLBACK CalcSum(int a,int b);vb中可以声明:Private declare Function MySum Lib "d:MyDLL.dll" (ByVal S As Integer, ByVal D As Integer) As Integer这样就可以在vb中使用了,可是我现在想在dll中写一个能够返回字符串的函数,并用vb的label控件把函数返回的字符串显示出来,请问dll里怎么写?vb里怎么声明?label控件怎么调用它?如能解决,立即给分,恳请大家帮帮忙!
回复1:__stdcall int CALLBACK CalcSum(int a,int b,char *c);vb中可以声明:Private declare Function MySum Lib "d:MyDLL.dll" (ByVal S As Integer, ByVal D As Integer, ByRef c as string) As Integer
回复2:BSTR/VARANT
回复3:用BSTRCString::AllocSysString BSTR AllocSysString ( )throw( CMemoryException );Return ValuePoints to the newly allocated string.或者SysAllocStringBSTR SysAllocString( OLEchar FAR* sz );
回复4:__stdcall char * CALLBACK CalcSum(int a,int b);在vb中定义函数的返回值就字符串类型或者字符指针就可以了。。。
回复5:vc寫dll,vb 調用,有趣。
回复6:BSTR, RETVAL, ByRef
回复7:试试:VB中String转换为VC中的BSTR,只要把参数类型改了就可以了,但要注意使用ByRef
回复8:/kb/187912
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:298719次
积分:4283
积分:4283
排名:第6101名
原创:106篇
转载:170篇
评论:23条
(1)(1)(1)(6)(10)(15)(2)(1)(1)(4)(7)(12)(11)(25)(25)(22)(4)(32)(12)(43)(41)真没想到VB也可以这样用之VB能做什么,VB教程,VB案例,VB实例
     本站短域名:珠江路.cn、zjlu.net
        
     
          
您的位置: &&
&& 真没想到VB也可以这样用之VB能做什么
真没想到VB也可以这样用之VB能做什么
  一直以来被认为有以下优缺点:优点是上手快、效率高;缺点是能力有限,运行效率低。这正是有些把VB做为首选语言,而有些软件肯定不会用VB做的原因。而很多VC,DELPHI的员都认为VB里搞开发不自由,它让我们做事变容易的同时,也让我们发挥的余地越来越小。的确,简单和强大这两者本身就是一对矛盾。那怕一行不写,仅仅起动运行一个空这样简单动作,VB在底下就为我们做了大量复杂的工作(决不仅仅是注册窗口类、窗口、起动消息这么简单),这些工作对是透明的。我们在感谢VB开发小组对我们程序员体贴入微的同时,不禁也要责怪为什么在文档中对这些底层的动作只字未提,虽然这些动作对最终的程序也许并无影响,但我们拥有知情权,更何况这些动作有时的确会影响我们的工作。
  然而,所有希望从本文得到&未公开秘密&的朋友你将会很失望,因为我能够知道的和你一样多,我们所能做的一切就是站在外面来猜VB在里面做了什么?所以我决不是要带大家一起去将VB反向工程,而是想通过猜想VB的内部工作来将一些原来比较模糊的搞清楚。作为一个系列的第一篇文章,它的目的是为了后面的深入打下,所以我会在需要的时候指出我们必须掌握的知识点,如果你不清楚,请及时地学习相关书籍来补课。
  最后,要我在本文中所做的各种实验和推断仅是我个人的观点,不能保证其正确性,并且不承担任何相关的法律责任。
  好,开始吧!首先准备好我们的武器,我下面要使用的工具主要有:VB6中文版+SP5(废话),还有SPY++、Dependency Walk和OLE Viewer(以下简称SPY和DEPEND和OLEVW,SPY在VB的common\tools\vb\下的SPY目录中,OLEVIEW是其下OLETOOLS目录中的OLEVIEW.EXE,注意其下还有一个OLE2VW32.EXE功能类似,不过本文所指的是OLEVIEW.EXE,还Denpend在其下的Unsupprt\DEPEND里)。还要用用VC(上面提的工具在VC里有),因为我们还要看看VB的代码,搞VB高级开发的朋友一定要会用VC器,懂点汇编更好。当然,本文的重点不在这儿,所以没有VC也不要紧。
  打开VB6新建一EXE工程,在&工程&-&&引用&对话框里应该已有四个引用,简单点就是:
  1、 Basic For licon(VBA)
  2、VB运行时库
  3、VB对象库
  4、OLE自动化。前面三个是任何VB工程都必须的,你想不要都不行,不信你试着去掉对它们的引用。那么这三个类型库各有什么用,在最终生成的可程序中扮演怎样的,这是本文要的第一个。
  1)VB、VBA、VBS的区别你搞清楚了吗?
  首先VBS不应该和VB、VBA放在一起比较,它是按照自己的ActiveX Scripting规范完全从头开始写成的语言,虽然它的和VB非常相似,但VBS仅仅依靠自动化对象来扩充其功能(只有后期绑定),它不能用implements来实现,不可能在VBS里直接使用I,没有VarPtr这样能得到指针的,而VBS缺少的这些功能正是VB和VBA所特有的。当然,这不是说VBS不如VB或VBA,已经为VBS提供了足够强大的功能,我们可以用VBS来做脚本COM组件,而且借自动化对象的能力VBS可以说能力无限,所以有用VBS来写,对程序员来说VBS最重要的功能莫过于可以给自己的软件提供宏功能,就象VC中提供的VBS宏功能那样。注意,VBS是Free的,这和在Office中使用VBA来提供宏功能不同,要集成VBA需要不低的证费用,关于可参见MSDN中Platform
SDK\Tools and Languages\Scripting。(在本系列后面的文章《脚本功能》中我会实做一个用VBS来提供宏功能的小软件)
那么VB和VBA又有什么不同呢?好吧,眼见为实,开始我们的实验吧!
  如果装了Office 2000以上版本,那么打开OLEVIEW,点击下的View TypeLib查看位于E:\gram Files\Common
Files\Microsoft Shared\VBA\VBA6下的VBE6.dll的类型库,再用同样的看看MSVB60.dll的类型库,你会发现它们的类型库基本上一模一样,除了VBE6多了一个VBEGlobal接口和实现这个接口的Global对象,这个Global对象我们也可以在VBA环境(比如用WORD的VB编辑器)中用对象看到。它有二个方法Load和UnLoad,还有一个Users,这是因为VBA6使用MS
Form器(FM20.dll)来设计和使用UserForm窗体(而在VB6中,我们可以使用多个设计器。比如通过使用MS Form 2.0
Form设计器,我们就能在VB中使用VBA所使用的UserForm窗体)。
  和VBA的Global对象类似,在VB中也有GLobal对象,从VB的对象浏览器中可以知道它在vb6.olb这个类型库中,这个类型库就是每个工程都必须引用的VB对象库,所有的VB都在这里。而VBA的UserForm中使用的对象都在FM20.dll中。
除了上述不同外,VB和VBA还有一个最大的不同,就是VBA不能生成EXE可执行,但可以猜想在环境中VBA和VB都要把代码成p-code来执行,后面我将用实验来证明的确是这样,虽然在具体的实现上VB和VBA有很大的不同。
  从上面的分析上可以看到VB和VBA还是有很大不同的,这种不同主要体现在编程环境和对象结构上,但在本质上它们之间却有着不可割舍的血源关系。如果刚才你仔细地观察了MSVBVM60.dll的类型库,你就会发现如下的片断:
// Generated .IDL file (by the OLE/COM Object Viewer)
dllname(&VBA6.&),
uuid(35BFBDA0-2BCC-69-82-00DD010EDFAA),
helpcontext(0x000f6ec4)
module Strings {
[entry(0x), helpcontext(0x000f665f)]
short _stdcall Asc([in] BSTR String);
[entry(0x), helpcontext(0x000f6e9f)]
BSTR _stdcall _B_str_Chr([in] long CharCode);
……………
  什么?在MSVBVM60.dll中的对象其方法却定义在VBA6.DLL中?!VB目录下不就有个VBA6.DLL吗?再用OLEVIEW看看它,哇噻,真是想不到它居然和MSVBVM60.DLL的一模一样。怎么回事?赶快再拿出DEPEND来看看VBA6.dll、MSVBVM60.dll和VBE6.dll这三个DLL的输出函数。哈,又有新发现,我们可以发现在三个DLL的输出函数中从编号512到717绝大部分都是一模一样的一些以rtc开头的函数,比如595的rtcMsgBox(rtc是什么?应该是Run
Time Component? ? Code?有谁知道吗?),这说明三个DLL都有着相同的运行时VBA函数。
我们再用DEPEND来观察一下VB6.EXE, 我们可以发现VB6.EXE引入了VBA6.DLL中一些它特有的以Eb和Tip开头的函数,从这些函数的名称上可以发现它们的功能都是IDE相关的,比如79的EbShowCode和82的TipDeleteModule。VB6.EXE恰恰没有引入任何rtc开头的函数(注意一)。我们再来看看MSVBVM60.DLL,随便找一个用了MsgBox函数的编译后的文件,用DEPEND来观察它,就会发现它引入MSVBVM60.DLL输出的595号rtcMsgBox函数(注意二)。并且引入MSVBVM60.DLL中很多以下划线开头的函数,比如__vbaVarAbs(注意三)。其实从这个三个&注意&中我们已经可以进行一些猜想,无论对错,你可以先想想。
  如果你没有跟着我做实验,而仅仅是看这篇文章的话,我猜想你应该有点昏了。如果你自己动手做了这些实验,现在你应该充满了疑问而急侍看到结论。所以请一定要亲手试一试,学习问题的方法比看结论更重要。
  到这里至少我们可以得出结论:VB和VBA本就是同宗的姐妹,只不过姐姐VB的功夫要比妹妹VBA历害些。不过姐姐只会单打独斗是女强人;妹妹却只会傍大款。姐姐有生育能力,是真正的女人;妹妹却不会生崽,但深谱相夫之道,一番教导指挥之下可使她老公增色不少,而VBS呢,也是大户人家的女儿,不过没有VB和VBA姐妹优秀的血统,娇小玲珑干不得粗活只能指挥些自动听话的对象来干活,她乐于助人品德好不象VBA那样只认大款,VB、VBA、vbs三个女人我都喜欢。
  2)Native Code(本地代码)到底做了什么?
  打起精神,我们再深入一步。用OLEVIEW得到的类型库还不能正确的反映各对象方法对应的DLL中的函数入口,你应该已经发现用OLEVIEW得到的IDL文件中各个方法的entry属性值都是0x600000XX这样的假东西。要得到类型库中各方法在DLL中的真正入口,我们需要自己来写段程序。
  即使在VB中我们也可以非常容易地获取类型库信息,再加上点COM初始化和调用代码,我们就能用自己的代码实现VB6才引入的CallByName函数(在本系列后面的《Hack
COM》中我会更深入谈谈COM,作为一名VB程序员对COM的理解非常重要)。由于本文的关键不是指导如何在VB里使用类型库,所以下面提供的方法尽量从简。
  新建一个标准EXE工程,添加对TypeLib Infomation的引用,在Form中放一个名为lblInfo的,然后添加如下代码:
Private Sub Form_Load()
 Dim oTLInfo As TypeLibInfo
 Dim oMemInfo As MemberInfo
 Dim sDllName As String
 Dim sOrdinal As Integer
 Set oTLInfo = TLI.TypeLibInfoFromFile(&MSVBVM60.DLL&)
 lblInfo = &MATH包含以下方法:& & vbCrLf
 For Each oMemInfo In oTLInfo.TypeInfos.NamedItem(&Math&).Members
  With oMemInfo
   .GetDllEntry sDllName, vbNullString, sOrdinal
   lblInfo = lblInfo & .Name & &定义在& & sDllName &
&中,& & &其编号为& & sOrdinal & vbCrLf
  End With
  运行以后我们就可以知道MATH模块中的Abs方法定义在VBA6.DLL中,其编号为656。在DEPEND中查看VBA6.DLL中编号为656的函数,果然就是rtcAbsVar,用VBE6.DLL试试结果相同。
  还记得前面的注意一吧,VB6.EXE没有引入rtc开头的函数这说明在IDE环境中执行的VBA方法实际上是通过COM调用VBA对象库中的方法(跟踪p-code是噩梦,所以我无法验证它用的是什么绑定)。而注意二中提到的最终可执行程序中引入了rtcMsgBox,如我们所料最终的程序会直接调用它,这要比COM调用快一点,但在跟踪最终程序时,我发现rtcMsgBox内部却是经过了二万五千里长征后才会去调用MessageBoxA这个,其间有多次对其它对象的COM调用,慢!可能是因为显示的是模态对话框,在多进程环境有很多需要考虑的因素吧,如果你是疯狂在意效率的程序员,你应该试试用API来重写MsgBox,绝对快不少。再来看看注意三,让我们把以下的程序编译成使用本地代码的&程序2.EXE&(为了后面的实验,可以在工程属性的编译选项卡它设成&无&和&生成符号化调试信息&程序2.EXE&&):
Private Declare Sub DebugBreak Lib &kernel32& ()
 Private Sub Main()
 Dim i As Long, j As Long
 i = &H1234
 DebugBreak
 k = 1234
 j = Abs(k)
 j = Abs(i)
 MsgBox &ss&
 j = VarPtr(i)
  用DEPEND观察&程序2.EXE&,我们可以发现&程序2.EXE&并没有如我们预期的一样在引入595的rtcMsgBox的同时引入656的rtcAbsVar,相反它引入了__vbaVarAbs和__vbaI4Abs,看看函数名就知道一个针对的是Variant,一个针对的是long。这说明VB在最终生成的代码中对象Abs这样的可以进一步针对不同类型优化的VBA函数进行了相应的,观察一下所有以__vba开头的函数绝大部分都是那些最基本最常用的VBA函数,可以说__vba开头的VBA函数是rtc开头的VBA函数的优化版本,它们基本上是VB开发小组重新写的,绝大多数在函数内部实现自身功能,而rtc开头的函数大多数是调用COM对象来完成工作。
  从这么多__vba开头的函数上可以看出VB小组在Native Code(本地代码)的优化上下了不少功夫,这决对不是吹牛。它的确优化了不少科学计算相关的函数,以ABS为例Native
Code要比p-code快4倍以上。但是并不是所有的计算函数都经过了这样的优化,比如Rnd函数,它就没有对应的__vba开头的,而是直接对应到rtcRandomNext函数上,虽然rtcRandomNext也已经优化过,但内部依然用了COM调用,还是不如自己重写的快,我不明白为什么VB开发小组没有考虑为它写一个对应的__vbaRnd。
  不要以为上面的分析没有意义,因为我们可以从现象看本质,也可以从本质来解释现象。比如我们再做一个实验,给你的代码加入一个类模块,你可以试试声明一个和内部方法同名的公有的方法,比如我们可以声明一个Public
Rnd(x) as single,同样我们可以自己写一个同名的MsgBox。但是你试试能不能声明一个Public Function abs(x)
,这时VB肯定会弹出一个莫名其妙的编译错误提示框告诉你&缺少符&,这种错误发生在你的函数名和VB关键字冲突的时候。
  但是为什么同样是MATH模块中的函数,abs是关键字,rnd却不是,VB文档里是不会告诉你为什么的,但如果你认真的看了我上面的实验分析,我们就能猜想这是因为VB对需要进一步优化的函数已经做了高度优化处理,VB开发小组为了他们的劳动成果,并显示他们对自己优化技术的自信,而禁止我们重写这些函数,同时VB开发小组也承认还有些函数有待进一步优化,所以准许我们重写之。在这里我要提出一个伟大的猜想:凡是能够被重写的函数就能够被优化,就象凡是大于2的偶数就能够被分解成两个质因数的和一样。
  说到优化,还应该谈谈直接API调用和使用API类型库的差别,还必须谈谈VB所使用的后端优化器(和VC用的是一样的优化器),还想谈谈如何尽最大可能来使用vTable绑定……
  看了本地代码,我们再来看看p-code,要是你看了MSDN中关于p-code的,你肯定会头大。平心而论p-code真是一个了不起的技术,代码大小平均可以缩小50%。我们把程序2编译成p-code看看,还是用DEPEND来观察,发现它并没有引入__vba开头函数(没有使用优化的VBA函数?),却引入了Call这样的东西(肯定是为了调用p-code伪码解释引擎),而且和Native
Code一样都引入了rtcMsgBox(编译生成的p-code在调用MsgBox时应该比在IDE环境中运行的p-code快)。
  如果你迫不及待地运行了程序2,你就会发现它将弹出一个程序错误对话框,说程序发生异常。别怕,这是因为调用了DebugBreak这个API的缘故,这个API其实就是产生一个Int
3中断,使得我们能够中断程序执行。如果你装了VC这样的支持即时调试的调试器,你可以在错误对话框中点击&取消&,这样可以起动调试器来调试程序。我就是这样跟踪程序运行的。如果你想看看VB生成的程序反汇编代码可以自己试试,我们可以用同样的技术在VB或VBA的IDE中来中断程序执行,比如我们完全可以在Word的VB编辑器中运行上面程序2的代码,从而中断于Word的进程中,并可观察到VBA生成的p-code代码。比如VB和VBA在IDE中生成的p-code代码就会发现它们这间有很大的不同。
  所以,IDE中运行的程序和最终生成的程序是完全不同的。用SPY++看看你在IDE中运行的窗体,你会发现它在VB的主线程下,也就是说在IDE中你用程序做出的窗体和VB
IDE工作窗口一样属于VB IDE,你的程序在IDE中运行时申请的也属于VB IDE。有些程序在IDE中运行会让IDE死掉(在VB5中写纯API多线程就千万别在IDE中运行,定死无疑,相比之下VB6的IDE健壮得多)。还有些程序可能在IDE中能正常工作,但生成EXE后就工作不了。总之,在写程序时要考虑到这种不同可能引起的问题。
  3)VB的编译技术,要我怎么夸你,又要我怎么骂你。
  看了上面对Native Code的高度评价,你可能会对VB做出的东西更有信心了,腰板更直了。是的,作为VB程序员没有什么需要害羞的,一个功力深厚的VB程序员理应拿比普通VC程序员更多的,因为他的生产力是VC程序员的好几倍,而做出的程序在质量上和VC做的相差无几。
  甚至有大师开玩笑说VB的内置对象就是用VB写出的,比如我们可以自己写Form.cls、Label.ctl,呵呵,我们还真不能这种可能性(虽然用VB不可能直接生成vb6.olb)。如果真是这样,看来VB小组自己都对自己的编译优化技术非常有信心。
  实际上我们看看VB安装目录下的C2.exe的属性,再看看VC的C2.DLL的属性,就会发现它们是同一个东西,同样Link.exe也是VC的,所以我们完全可以对VB程序的后端优化编译器以及联结放心了。它们根本就是VC开发小组东西,或者VB、VC都是同一个编译器开发小组在做编译模块。总之,我们可以壮着胆说我们VB做的程序其二次优化和联结用的是和VC一样的技术,嘿嘿,你有的我也有,我有的你没有的(纯属诡辩)。
  还有,没有任何编译器比VB编译器更快,因为在IDE中VB就是一种解释型语言,这才是VB开发效率高的关键,快得几乎感觉不得编译。其时编译,后台编译技术更是一只独秀,厉害啊!想想看,别的语言的程序员有多少时间花在了等待代码编译和重新联结上啊!
不要高兴得太早,因为最终的目的还是要生成可执行文件。在VB中没有分块编译和增量联结的功能,VB在生成可执行程序时总是编译所有模块并完全重新联结,而在别的编译语言中我们可以仅编译最近修改过的文件(分块编译),联结时将新生成的代码附在可执行程序的后面,并将原来的代吗为作废(增量联结,最终的可执行程序会越来越大,但联结时间大大缩短)。做实验看看,会发现在VB中每次生成可执行文件所花时间都是相同的。
  我不知VB开发小组为什么不提供分块编译和增量联结的功能,可能VB开发小组认为生成可执行文件在VB中不是经常要做的工作。但是实际上这种理由是说不过去的,因为如前面所说IDE中运行程序和最终程序有很大不同,如我们要经常编译出可执行文件才能真正对它进行,又如我们要调试多线程程序不能在VB
IDE中做,在这些情况下每次修改后都要重新生成可执行文件,我们浪费了不少时间去编译已编译过的代码,联结已联结过的程序。我猜想这是因为VB生成可执行程序时进行了全局优化,所以必须得全部重新编译联结。但提供一个新的功能让我们能够生成不进行全局优化的可以分块编译的调试版本,对Vb开发小组应该不是难事吧!(我有一个变通的,还在试验中)
  在来看看VB6安装目录下的VBAEXE6.lib,怎么只有1k大一点,可以猜想里面应该不会有代码,多半是些象vTable这样的函数地址跳转表,或者是些全局,我也不知道。但至少说明VB可以用联结库了,为什么不把这个功能提供给我们,让我们有更多的选择。
  再做个实验看看,做一个标准EXE工程,里面只有一个标准模块,模块里面只一个Sub Main,Sub Main里面什么也没有,将它生成为EXE文件。看看,嚯,有16k多。你要是有时间跟踪这个什么也不做的程序看看,就会知道它要做很多事,初始化Err和App对象,准备COM调用,准备VB、VBA对象库,甚至为使用ActiveX控制也做了准备,嘿嘿,看服务多周到。你必须得用VB对象库中的控制,不用也不行。你再多找几个EXE工程看看,有很多东西相同,都是一个模子做出的,而且你没有选择模子自由。ActiveX工程也是一样,都是Dual双接口,你做的ActiveX控制都必须要躲在一个
Object后面。是的,在VB里有很多东西你没有选择的自由。如果需要这种自由要么不用VB,要么就得采取一些未公开的非官方的古怪的(本系列文章最重要的目的之一,就是介绍这样的非官方技巧)。
  这又到文章开头说的,VB让我们做事情变得容易的同时也让我们失去了不少自由。在最终代码的生成上则也采取了公式化的做法。当然,我们应该全面地来看待这个问题,如同生产线上生产的东西不一定比手工的精致,群养的家禽不如野味好吃的道理一样,如果需要精致的野味,意味着更多的劳动和更大的,这和VB所追求的更容易更的目标是相违背的。
  4)VB程序员也得有HACK精神。
  本文的最后这个标题是严重离题了,但我想在此为本系列文章定下一个充满HACK精神的基调。HACK精神是什么?没有准确的定义,我的理解是:HACK精神 =
总想探寻未知领域的好奇心 + 凡事总想知道为什么的研究欲 + 总想拿出自己的东西的创新精神 + 解决问题的耐心和恒心。 VB的程序员也一样需要这种精神。
  最后,我们都知道VB开发小组已经达上.NET的快车飞起来了,不能不说VB6以后再没有VB的新版本了。微软已经用.NET为我们划出了新的圈子,是这个新圈子里的新产物。在圈子里面我们能够飞得更高,但是圈子外面的天空更大,所以我依然乐意站在圈子外,虔诚地祈祷真正的VB7的,阿门。
数据库开发
产品库推荐
All Rights Reserved.
珠江路在线版权所有
 |  |  | VB6与DLL函数
数组传递的问题用VC6编写了一个DLL。DLL中有一个函数 需要根据VB6传过来的几个数据生成一个数组,而后把数组的值传回给VB6.具体代码如下:// 整数转BCD码,4位数转存后为2个字节 比如1234 转存后为两个字节 低字节高4位为3 低4位为4 高字节高4位为1 低4位为2 &extern &C& _declspec(dllexport) char _stdcall int2b(int shu , unsigned char *outArr ){
&unsigned char E1,E2,E3,E4 ; &int shu2;
&E4=int(shu/1000); &shu2=shu-E4 * 1000; &E3=int(shu2/100); &shu2=shu2-E3 * 100; &E2=int(shu2/10); &shu2=shu2-E2 * 10; &E1=shu2;
&outArr[0]= (E2&&4) | (E1&15); &outArr[1] =(E4&&4) | (E3&15); &return 1;}VB6中的调用代码如下:Dim sz(10) As ByteDim BH As LongDIM I AS LONGFOR I=0 TO 10 & sz(I)=0NEXT IBH = 1234A = int2b(BH, sz(0))以上代码得到的结果却是sz(0)=86 sz(1)=185在VC中调试此代码得到的结果是第一个值为&H34=52,第二个值是&H12=18 为什么VB6调用DLL中的此函数后,得到的结果却不对呢。
& 另外还发现,如果把函数 &extern &C& _declspec(dllexport) char _stdcall int2b(int shu , unsigned char *outArr ){
&outArr[0]=39;(当然这个数随意) &outArr[1]=231;(当然这个数随意) &return 1;}VB调用此函数后的数是与函数中的赋值是一致的.请问是何原因。
求BCD码没必要用C DLL这么复杂的技术吧。  VB code  Private Sub Command1_Click()
Dim bb() As Byte
bb = int2bcd(&H1234)
Debug.Print &bb(0)=&h& + Right(&0& + Hex(bb(0)), 2) + &,bb(1)=&h& + Right(&0& + Hex(bb(1)), 2)
'整数转BCD码,4位数转存后为2个字节 比如4660=&h1234 转存后为两个字节 低字节高4位为3 低4位为4 高字节高4位为1 低4位为2
Public Function int2bcd(i As Integer) As Byte()
Dim b() As Byte
Dim h As String * 4
ReDim b(1)
h = Right(&000& + Hex(i), 4)
b(0) = CByte(&&h& + Right(h, 2))
b(1) = CByte(&&h& + Left(h, 2))
int2bcd = b
End Function
lingronaldo
1、VC的变量运算要求很严格,即使VC的代码看起来和VB的差不多,但计算的结果也不见得一样。
因为VC中没有那么只能的数据转换过程,而且变量的定义初始值也不一样,VB的是&H00,VC的
是0xFF,这也都可能是导致运算结果不对的因素。2、VC理解接VB传递过来的是个内存指针,而不是什么数组的概念,所以在VC中操作的是指针地址里
的值,而不是VB数组结构。在这个过程中,之所以用到指针的指针,主要是方便接口程序重新分配
内存,然后不至于改变原来指针的地址才这样运用。你可以在VC里尝试单步调试,先看看VC代码运算的结果是否正确,如果结果正确,再看看要返回数据的指针地址是多少,然后在VB中调用完VC的函数取得的指针地址也显示出来看看,看看是否是VC返回的相同的内存地址,这样一层一层调试,总会发现问题所在的。
在moudle中加上以下声明:declare function int2b lib &libname.dll& ( byval shu as long, outArr as any) as byte调用时以这种方式调用:A = int2b(BH, sz(0))经过试验,在vb中得出52和18的结果。检查一下你使用的dll是不是你在vc中最终生成的那个。
lingrongjian}

我要回帖

更多关于 vc string format 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信