| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 4932 人关注过本帖
标题:调用自定义函数的问题
取消只看楼主 加入收藏
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
结帖率:75%
收藏
已结贴  问题点数:20 回复次数:12 
调用自定义函数的问题
程序中调用自定义函数,实例如MD5('11aa'),生成登录密码。在VFP环境中运行正常,说明自定义函数MD5本身没问题,能用。编译成EXE文件后运行,则报错“函数参数的值、类型或数目无效”,以及文件 'lwordarray.prg' 不存在、无效的下标引用等。其中lwordarray其实是此函数中的一个数组,报错成lwordarray.prg文件不存在了。MD5函数是在网上找到的,比较流行,其代码如下:

FUNCTION LShift(lvalue,iShiftBits)
IF iShiftBits=0 THEN
    RETURN lvalue
ELSE
    IF iShiftBits=31 THEN
        IF BITAND(lvalue,1)<>0 THEN
            RETURN 0x80000000
        ELSE
            RETURN 0
        ENDIF
    ENDIF
ENDIF
IF BITAND(lValue,m_l2Power(32-iShiftBits))<>0 THEN
    RETURN BITOR((BITAND(lValue,m_lOnBits(32-(iShiftBits+1)))*m_l2Power(iShiftBits+1)),0x80000000)
ELSE
    RETURN BITAND(lvalue,m_lOnBits(32-iShiftBits))*m_l2Power(iShiftBits+1)
ENDIF
ENDFUNC
FUNCTION RShift(lvalue,iShiftBits)
IF iShiftBits=0 THEN
    RETURN lvalue
ELSE
    IF iShiftBits=31 THEN
        IF BITAND(lvalue,0x80000000) THEN
            RETURN 1
        ELSE
            RETURN 0
        ENDIF
    ENDIF
ENDIF
RShift2=INT(BITAND(lvalue,0x7FFFFFFE)/m_l2Power(iShiftBits+1))
IF BITAND(lvalue,0x80000000)<>0 THEN
    RShift2=BITOR (RShift2,INT(0x40000000/m_l2Power(iShiftBits)))
ENDIF
RETURN RShift2
ENDFUNC
FUNCTION RotateLeft(lvalue,iShiftBits)
RETURN BITOR(LShift(lvalue,iShiftBits),RShift(lvalue,(32-iShiftBits)))
ENDFUNC
FUNCTION AddUnsigned(lX,lY)
lX8=BITAND(lX,0x80000000)
lY8=BITAND(lY,0x80000000)
lX4=BITAND(lX,0x40000000)
lY4=BITAND(lY,0x40000000)
lResult=BITAND(lX,0x3FFFFFFF)+BITAND(lY,0x3FFFFFFF)
IF BITAND(lX4,lY4)<> 0 THEN
    lResult=BITXOR(BITXOR(BITXOR(lResult,0x80000000),lX8),lY8)
ELSE
    IF BITOR(lX4,lY4)<> 0 THEN
        IF BITAND(lResult,0x40000000)<> 0 THEN
            lResult=BITXOR(BITXOR(BITXOR(lResult,0xC0000000),lX8),lY8)
        ELSE
            lResult=BITXOR(BITXOR(BITXOR(lResult,0x40000000),lX8),lY8)
        ENDIF
    ELSE
        lResult=BITXOR(BITXOR(lResult,lX8),lY8)
    ENDIF
ENDIF
RETURN lResult
ENDFUNC
FUNCTION md5_F(x,Y,z)
RETURN BITOR(BITAND(x,Y),BITAND(BITNOT(x),z))
ENDFUNC
FUNCTION md5_G(x,Y,z)
RETURN BITOR(BITAND(x,z),BITAND(Y,BITNOT(z)))
ENDFUNC
FUNCTION md5_H(x,Y,z)
RETURN BITXOR(BITXOR(x,Y),z)
ENDFUNC
FUNCTION md5_I(x,Y,z)
RETURN BITXOR(Y,BITOR(x,BITNOT(z)))
ENDFUNC
PROCEDURE md5_FF(a,b,c,d,x,s,ac)
a=AddUnsigned(a,AddUnsigned(AddUnsigned(md5_F(b,c,d),x),ac))
a=RotateLeft(a,s)
a=AddUnsigned(a,b)
ENDPROC
PROCEDURE md5_GG(a,b,c,d,x,s,ac)
a=AddUnsigned(a,AddUnsigned(AddUnsigned(md5_G(b,c,d),x),ac))
a=RotateLeft(a,s)
a=AddUnsigned(a,b)
ENDPROC
PROCEDURE md5_HH(a,b,c,d,x,s,ac)
a=AddUnsigned(a,AddUnsigned(AddUnsigned(md5_H(b,c,d),x),ac))
a=RotateLeft(a,s)
a=AddUnsigned(a,b)
ENDPROC
PROCEDURE md5_II(a,b,c,d,x,s,ac)
a=AddUnsigned(a,AddUnsigned(AddUnsigned(md5_I(b,c,d),x),ac))
a=RotateLeft(a,s)
a=AddUnsigned(a,b)
ENDPROC
FUNCTION Hex(lByte)
x=''
DO WHILE lByte>0
    IF lByte>=16 THEN
        Y=lByte%16
    ELSE
        Y=lByte
    ENDIF
    IF Y<10 AND Y>=0 THEN
        x=STR(Y,1)+x
    ELSE
        x=CHR(65+Y-10)+x
    ENDIF
    lByte=(lByte-Y)/16
ENDDO
RETURN x
ENDFUNC
FUNCTION WordToHex(lvalue)
lResult=''
FOR lCount=0 TO 3
    lByte=BITAND(RShift(lvalue,lCount*BITS_TO_A_BYTE),m_lOnBits(BITS_TO_A_BYTE))
    lResult=lResult+RIGHT("00"+Hex(lByte),2)
ENDFOR
RETURN lResult
ENDFUNC

*主函数在这里
FUNCTION MD5(sMessage,lRetuLength)
IF PARAMETERS()<1 THEN
    RETURN
ENDIF
IF PARAMETERS()=1 THEN
    m.lRetuLength=16
ENDIF
IF PARAMETERS()>1 AND VARTYPE(m.lRetuLength)#'N' THEN
    m.lRetuLength=16
ENDIF
BITS_TO_A_BYTE=8
BYTES_TO_A_WORD=4
BITS_TO_A_WORD=32
DIME m_lOnBits(31)
DIME m_l2Power(31)
m_lOnBits(1)=1
m_lOnBits(2)=3
m_lOnBits(3)=7
m_lOnBits(4)=15
m_lOnBits(5)=31
m_lOnBits(6)=63
m_lOnBits(7)=127
m_lOnBits(8)=255
m_lOnBits(9)=511
m_lOnBits(10)=1023
m_lOnBits(11)=2047
m_lOnBits(12)=4095
m_lOnBits(13)=8191
m_lOnBits(14)=16383
m_lOnBits(15)=32767
m_lOnBits(16)=65535
m_lOnBits(17)=131071
m_lOnBits(18)=262143
m_lOnBits(19)=524287
m_lOnBits(20)=1048575
m_lOnBits(21)=2097151
m_lOnBits(22)=4194303
m_lOnBits(23)=8388607
m_lOnBits(24)=16777215
m_lOnBits(25)=33554431
m_lOnBits(26)=67108863
m_lOnBits(27)=134217727
m_lOnBits(28)=268435455
m_lOnBits(29)=536870911
m_lOnBits(30)=1073741823
m_lOnBits(31)=2147483647
m_l2Power(1)=1
m_l2Power(2)=2
m_l2Power(3)=4
m_l2Power(4)=8
m_l2Power(5)=16
m_l2Power(6)=32
m_l2Power(7)=64
m_l2Power(8)=128
m_l2Power(9)=256
m_l2Power(10)=512
m_l2Power(11)=1024
m_l2Power(12)=2048
m_l2Power(13)=4096
m_l2Power(14)=8192
m_l2Power(15)=16384
m_l2Power(16)=32768
m_l2Power(17)=65536
m_l2Power(18)=131072
m_l2Power(19)=262144
m_l2Power(20)=524288
m_l2Power(21)=1048576
m_l2Power(22)=2097152
m_l2Power(23)=4194304
m_l2Power(24)=8388608
m_l2Power(25)=16777216
m_l2Power(26)=33554432
m_l2Power(27)=67108864
m_l2Power(28)=134217728
m_l2Power(29)=268435456
m_l2Power(30)=536870912
m_l2Power(31)=1073741824
S11=7
S12=12
S13=17
S14=22
S21=5
S22=9
S23=14
S24=20
S31=4
S32=11
S33=16
S34=23
S41=6
S42=10
S43=15
S44=21
*********Function ConvertToWordArray(sMessage)
MODULUS_BITS=512
CONGRUENT_BITS=448
lMessageLength=LEN(sMessage)

lNumberOfWords=(INT((lMessageLength+INT((MODULUS_BITS-CONGRUENT_BITS)/BITS_TO_A_BYTE))/INT(MODULUS_BITS/BITS_TO_A_BYTE))+1)*INT(MODULUS_BITS/BITS_TO_A_WORD)
PUBLIC lWordArray(lNumberOfWords)   &&报错时说这个lWordArray.prg不存在,其实是个数组,已在此定义过
STORE 0 TO lWordArray
lBytePosition=0
lByteCount=0
DO WHILE lByteCount<lMessageLength
    lWordCount=INT(lByteCount/BYTES_TO_A_WORD)
    lBytePosition=MOD(lByteCount,BYTES_TO_A_WORD)*BITS_TO_A_BYTE
    lWordArray(lWordCount+1)=BITOR(lWordArray(lWordCount+1),LShift(ASC(SUBSTR(sMessage,lByteCount+1,1)),lBytePosition))
    lByteCount=lByteCount+1
ENDDO
lWordCount=INT(lByteCount/BYTES_TO_A_WORD)
lBytePosition=MOD(lByteCount,BYTES_TO_A_WORD)*BITS_TO_A_BYTE

lWordArray(lWordCount+1)=BITOR(lWordArray(lWordCount+1),LShift(0x80,lBytePosition))
lWordArray(lNumberOfWords-1)=LShift(lMessageLength,3)
lWordArray(lNumberOfWords)=RShift(lMessageLength,29)
***************************
a=0x67452301
b=0xEFCDAB89
c=0x98BADCFE
d=0x10325476
PUBLIC x(lNumberOfWords)
FOR k=1 TO lNumberOfWords
    x(k)=lWordArray(k)
ENDFOR

*****设置错误处理程序
ON ERROR DO err_treat
FOR k=1 TO lNumberOfWords STEP 16
    AA=a
    BB=b
    CC=c
    DD=d
    DO md5_FF WITH a,b,c,d,x(k+0),S11,0xD76AA478
    DO md5_FF WITH d,a,b,c,x(k+1),S12,0xE8C7B756
    DO md5_FF WITH c,d,a,b,x(k+2),S13,0x242070DB
    DO md5_FF WITH b,c,d,a,x(k+3),S14,0xC1BDCEEE
    DO md5_FF WITH a,b,c,d,x(k+4),S11,0xF57C0FAF
    DO md5_FF WITH d,a,b,c,x(k+5),S12,0x4787C62A
    DO md5_FF WITH c,d,a,b,x(k+6),S13,0xA8304613
    DO md5_FF WITH b,c,d,a,x(k+7),S14,0xFD469501
    DO md5_FF WITH a,b,c,d,x(k+8),S11,0x698098D8
    DO md5_FF WITH d,a,b,c,x(k+9),S12,0x8B44F7AF
    DO md5_FF WITH c,d,a,b,x(k+10),S13,0xFFFF5BB1
    DO md5_FF WITH b,c,d,a,x(k+11),S14,0x895CD7BE
    DO md5_FF WITH a,b,c,d,x(k+12),S11,0x6B901122
    DO md5_FF WITH d,a,b,c,x(k+13),S12,0xFD987193
    DO md5_FF WITH c,d,a,b,x(k+14),S13,0xA679438E
    DO md5_FF WITH b,c,d,a,x(k+15),S14,0x49B40821
    DO md5_GG WITH a,b,c,d,x(k+1),S21,0xF61E2562
    DO md5_GG WITH d,a,b,c,x(k+6),S22,0xC040B340
    DO md5_GG WITH c,d,a,b,x(k+11),S23,0x265E5A51
    DO md5_GG WITH b,c,d,a,x(k+0),S24,0xE9B6C7AA
    DO md5_GG WITH a,b,c,d,x(k+5),S21,0xD62F105D
    DO md5_GG WITH d,a,b,c,x(k+10),S22,0x2441453
    DO md5_GG WITH c,d,a,b,x(k+15),S23,0xD8A1E681
    DO md5_GG WITH b,c,d,a,x(k+4),S24,0xE7D3FBC8
    DO md5_GG WITH a,b,c,d,x(k+9),S21,0x21E1CDE6
    DO md5_GG WITH d,a,b,c,x(k+14),S22,0xC33707D6
    DO md5_GG WITH c,d,a,b,x(k+3),S23,0xF4D50D87
    DO md5_GG WITH b,c,d,a,x(k+8),S24,0x455A14ED
    DO md5_GG WITH a,b,c,d,x(k+13),S21,0xA9E3E905
    DO md5_GG WITH d,a,b,c,x(k+2),S22,0xFCEFA3F8
    DO md5_GG WITH c,d,a,b,x(k+7),S23,0x676F02D9
    DO md5_GG WITH b,c,d,a,x(k+12),S24,0x8D2A4C8A
    DO md5_HH WITH a,b,c,d,x(k+5),S31,0xFFFA3942
    DO md5_HH WITH d,a,b,c,x(k+8),S32,0x8771F681
    DO md5_HH WITH c,d,a,b,x(k+11),S33,0x6D9D6122
    DO md5_HH WITH b,c,d,a,x(k+14),S34,0xFDE5380C
    DO md5_HH WITH a,b,c,d,x(k+1),S31,0xA4BEEA44
    DO md5_HH WITH d,a,b,c,x(k+4),S32,0x4BDECFA9
    DO md5_HH WITH c,d,a,b,x(k+7),S33,0xF6BB4B60
    DO md5_HH WITH b,c,d,a,x(k+10),S34,0xBEBFBC70
    DO md5_HH WITH a,b,c,d,x(k+13),S31,0x289B7EC6
    DO md5_HH WITH d,a,b,c,x(k+0),S32,0xEAA127FA
    DO md5_HH WITH c,d,a,b,x(k+3),S33,0xD4EF3085
    DO md5_HH WITH b,c,d,a,x(k+6),S34,0x4881D05
    DO md5_HH WITH a,b,c,d,x(k+9),S31,0xD9D4D039
    DO md5_HH WITH d,a,b,c,x(k+12),S32,0xE6DB99E5
    DO md5_HH WITH c,d,a,b,x(k+15),S33,0x1FA27CF8
    DO md5_HH WITH b,c,d,a,x(k+2),S34,0xC4AC5665
    DO md5_II WITH a,b,c,d,x(k+0),S41,0xF4292244
    DO md5_II WITH d,a,b,c,x(k+7),S42,0x432AFF97
    DO md5_II WITH c,d,a,b,x(k+14),S43,0xAB9423A7
    DO md5_II WITH b,c,d,a,x(k+5),S44,0xFC93A039
    DO md5_II WITH a,b,c,d,x(k+12),S41,0x655B59C3
    DO md5_II WITH d,a,b,c,x(k+3),S42,0x8F0CCC92
    DO md5_II WITH c,d,a,b,x(k+10),S43,0xFFEFF47D
    DO md5_II WITH b,c,d,a,x(k+1),S44,0x85845DD1
    DO md5_II WITH a,b,c,d,x(k+8),S41,0x6FA87E4F
    DO md5_II WITH d,a,b,c,x(k+15),S42,0xFE2CE6E0
    DO md5_II WITH c,d,a,b,x(k+6),S43,0xA3014314
    DO md5_II WITH b,c,d,a,x(k+13),S44,0x4E0811A1
    DO md5_II WITH a,b,c,d,x(k+4),S41,0xF7537E82
    DO md5_II WITH d,a,b,c,x(k+11),S42,0xBD3AF235
    DO md5_II WITH c,d,a,b,x(k+2),S43,0x2AD7D2BB
    DO md5_II WITH b,c,d,a,x(k+9),S44,0xEB86D391
    a=AddUnsigned(a,AA)
    b=AddUnsigned(b,BB)
    c=AddUnsigned(c,CC)
    d=AddUnsigned(d,DD)
ENDFOR
ON ERROR &&恢复默认的错误处理
IF m.lRetuLength=32 THEN
    RETURN LOWER(WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d))
    &&输出32位代码
ELSE
    RETURN LOWER(WordToHex(b)+WordToHex(c)) &&输出16位代码
ENDIF
ENDFUNC
PROCEDURE err_treat
RETURN &&在此设置错误处理程序
ENDPROC

上述代码我先是保存为一个独立的prg文件,在表单的init里通过SET PROCEDURE TO mymd5.prg调用,出问题后改为放在main.prg里,也是同样出现上述错误。
为什么在VFP环境中运行正常,而编译成EXE文件后却报错了呢?
搜索更多相关主题的帖子: WITH DO RETURN IF THEN 
2019-11-27 22:23
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
收藏
得分:0 
没有选择,一直没碰这项。
况且,这是VFP环境内的设置,而在vfp环境中运行是没有问题的。是编译成EXE文件后运行,这个MD5函数才出错,似乎是离开VFP环境后缺了什么东东导致。
2019-11-27 22:49
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
收藏
得分:0 
大家可以测试一下,随便建一项目,在main.prg中加入这堆MD5的代码,建一个表单,放一个按钮,按钮的CLICK下写messagebox(md5('123'))。此时运行表单,点击该按钮,应该正常弹出经过加密的字串。然后编译成EXE文件,再运行,点击按钮,就会报错。
2019-11-27 22:58
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
收藏
得分:0 
与这个messagebox没关系,仅用来测试。问题的焦点是:这个md5函数,在编译前一切正常,编译后出错。
这个函数的调用方法是:md5('这里放数字、字母组成的密码'),比如vpwd=md5('abc123')。此句编译前正常,编译后出错。是这样的问题。
2019-11-28 10:05
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
收藏
得分:0 
具体的出错位置是在这个md5函数体内,可能还有其用到的周边几个函数,弹出的出错信息是“函数参数的值、类型或数目无效”,细看error(),还有“文件 'lwordarray.prg' 不存在”、“无效的下标引用”等错误信息。lwordarray其实是函数内已定义的一个数组。

[此贴子已经被作者于2019-11-28 10:18编辑过]

2019-11-28 10:17
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
收藏
得分:0 
vfp_md5.rar (25.08 KB)

此压缩包是测试用的项目,麻烦大家试试。
2019-11-28 11:54
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
收藏
得分:0 
你还没编译吧,在vfp编程环境直接运行表单,确实是一切正常。你把项目编译成EXE后再运行试试看。
感觉应该不是路径问题,如果是路径问题,那首先是找不到这个文件。现在是函数运行起来了啊,只是有问题而已。

这里再说明一下:这个测试项目编译成exe文件后,运行这个文件,点击“登录”按钮,如果出错,程序会把错误信息写入当前目录下的一个文本文件,打开这个文件,可以看到很多个错误,主要是文件 'lwordarray.prg' 不存在以及无效的下标引用。但其实并没有lwordarray.prg这个文件,它就是一个数组lwordarray(1)。当没有定义一个数组就直接引用时VFP往往抛出这种错误。至于这个“无效的下标引用”的错误,虽不知道是在哪一行,但至少说明函数是跑起来了,也许是前面的错误导致下标值异常才引发这个错误。

麻烦大家帮试一下:
打开项目后,先运行“代码”页的path程序,用于配置路径;再运行“文档”页的mainfrm表单,点击“登录”,此时应该是正常的。然后编译成Exe文件,再运行这个exe文件,点击“登录”,应该是报错。点击报错窗口的“取消”,程序关闭,同时生成一个文本文件,记录所有的错误。

[此贴子已经被作者于2019-11-28 13:37编辑过]

2019-11-28 13:21
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
收藏
得分:0 
问题是在vfp编程环境下是好好的,说明路径没问题,数组也声明了,不然没等编译,错误就应该出来了。
编译好的exe文件,也是在当前文件夹下的呀!

里面有这句,应该是声明了吧:
lNumberOfWords=(INT((lMessageLength+INT((MODULUS_BITS-CONGRUENT_BITS)/BITS_TO_A_BYTE))/INT(MODULUS_BITS/BITS_TO_A_BYTE))+1)*INT(MODULUS_BITS/BITS_TO_A_WORD)
PUBLIC lWordArray(lNumberOfWords)

原代码用的是
DIME lWordArray(lNumberOfWords )
出现问题后我改为 PUBLIC lWordArray(lNumberOfWords)
还是不行。
2019-11-28 19:49
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
收藏
得分:0 
这个项目的全部功能都弄好了,就等编译后开始交付试用。现在竟然卡在这点上,真抓狂
2019-11-28 19:54
gxbsdzf
Rank: 2
等 级:论坛游民
帖 子:28
专家分:23
注 册:2019-11-26
收藏
得分:0 
妥了!原来如此!!!
确实是main.prg中那句SET COMPATIBLE ON的设置,导致md5函数中的STORE 0 TO lWordArray这句把已声明为数组的lWordArray改写为同名的普通变量了!
而mainm.prg是编译时才包含进来的。这才造成vfp编程环境下正常,而在EXE文件中出错的怪现象。

改为
SET COMPATIBLE OFF
vmm=MD5(vmm)
SET COMPATIBLE ON
就正常了。或者如版主在18楼说的方法也一样行。

感谢版主!高手就是高手!这么细微的错误也只有高手能排查出来。十分感谢!!吃一堑长一智,又学到一招!
2019-11-28 23:22
快速回复:调用自定义函数的问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017898 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved