最近调一个医保接口,就一个声明和调用的问题上卡了一个星期没有解决,和接口商只要到了一个dephi的声明,而我用的是VB,怎么整都不行,请大家帮帮我吧,我已经发一个帖子[Dephi声明如何转VB声明],不少朋友给了我热心的帮助,但是天不帮我,还没调通.现在我把整个调试环境发给大家,哪位不忙不妨调调
     匿名提取文件连接 http://pickup.mofile.com/7587685010050640  
     或登录Mofile,使用提取码 7587685010050640 提取文件 我在此致以最最崇高的感谢!!!

解决方案 »

  1.   

    可能某些参数不一定兼容 VB 的 API 调用,你可以要求对方提供一个 C 的调用例子,然后看看能否转成 VB。
      

  2.   

    能下载啊,打开http://pickup.mofile.com/7587685010050640
    ,点击[下载文件(IE浏览器)],不能下载可能是你的IE或防火墙阻止了吧
    或者打开http://file.mofile.com,输入提取码7587685010050640,然后[提取文件]
      

  3.   

    下载不了,你不如上传到CSDN资源上:http://u.download.csdn.net/upfile/
      

  4.   

    各位高手朋友可以看一下楼主的原帖链接。Public Declare Function checkuser Lib "zdtlmti.dll" _
        (ByVal lpstrOperID As Long, ByVal lpstrReturnMessage As Long) As LongSub test()
        Dim strOperId As String
        Dim strMsg As String
        
        '字符串初始化'
        strOperId = "{F9AEE43D-E6B6-4787-84CC-FCB92F05A9DC}"
        strMsg = String$(200, 0)
        '完成其他调用该函数之前需要的初始化工作:’
        '比如你在16楼说的生成表和修改配置'
        
        '根据zdtlmti.dll具体情况,以下两种写法选择一种:'
        
        '(1)如果zdtlmti这个库接受的是UNICODE字符串, 用以下代码'
        checkuser StrPtr(strOperId), StrPtr(strMsg)
        MsgBox strMsg
        
        '(2)如果zdtlmti这个库接受的是ANSI字符串,用以下代码'
        strOperId = StrConv(strOperId, vbFromUnicode)
        strMsg = StrConv(strMsg, vbFromUnicode)
        checkuser StrPtr(strOperId), StrPtr(strMsg)
        MsgBox strMsg
        strMsg = StrConv(strMsg, vbUnicode)
    End Sub
      

  5.   

    我把测试环境上传到了以下地址
    http://zbl5174.download.csdn.net/
      

  6.   

    function checkuser(OperID: PChar; var returnMessage: pchar):Integer 
    在网上找了一些有关DEPHI 的var参数的一些区别,以上各位并没有注意到这个var,也许以为变量,就是变量吧。 
    这个var加上参数的时候,DEPHI会做一些特殊的处理:自动转变这一参数为一个地址 
    按照我的理解,这个声明如果转化成VB语言的话,应该是 
    function checkuser(Byval OperID As String, 
                      Byref returnMessage As String) as Integer 
      

  7.   


    你最好不要声明为String,因为VB会对动态库调用的字符串参数自动做Unicode到ANSI的转换,可能会导致你的结果不正确。你先弄清楚你的动态库的字符串是Unicode编码还是ANSI编码。另外,7楼的代码你看了并且试了么?
      

  8.   

    昨天我梦到你的动态库是ANSI的,哈哈。
      

  9.   

    我这儿没SQL Server,也不会用它,没法试。另外,7楼的代码你单步跟过没?在哪一行挂的?
      

  10.   

    如果 PChar 是 char*,那么 var ... PChar 就是 char**?
    试试这个
    Option ExplicitPublic Declare Function checkuser Lib "zdtlmti.dll" _
        (ByVal OperID As String, ByRef pReturnMessage As Long) As LongSub test()
        Dim strOperId As String
        Dim strMsg As String
        Dim a() As Byte
        Dim ptr As Long
        Dim i As Long
        
        strOperId = "{F9AEE43D-E6B6-4787-84CC-FCB92F05A9DC}"
        ReDim a(0 To 200)
        ptr = VarPtr(a(0))
        Debug.Print Hex(ptr)
        
        checkuser strOperId, ptr
        
        Debug.Print Hex(ptr) '确认一下指针是否不变'
        
        i = InStrB(1, a, ChrB(0))
        If i = 0 Then i = 201
        strMsg = StrConv(LeftB(a, i - 1), vbUnicode)
        
        MsgBox strMsg
    End Sub
      

  11.   

    你最好让对方提供一个可成功运行的 C 例子,这样方便翻译成 VB。
    如果 C 都不能调用成功,就是 dll 本身的问题了。
      

  12.   

    7楼的代码我试了,
    就在r=checkuser StrPtr(strOperId), StrPtr(strMsg这一行挂的
      

  13.   


    7楼有两个checkuser StrPtr(strOperId), StrPtr(strMsg)你在哪个挂的?
      

  14.   

    我找了一个以前在公司干过的老同事给调试了一下,他反汇编追踪dll的某个地址过不去,如果进一步解决的话,得要两个星期才能弄出个究竟,然后把Dll重新编译一下.
    他分析说dll本身不应该有什么问题,这是VB的不足,傻瓜实用,但是很多细的地方微软处理得不够精明;
    他建议先通过其它调试手段调着,没必要在这个问题上叫针儿,除非非得单步调试,他说可以用C类语言再写个
    Dll,把这个dephi写的Dll包起来,我听了好像就是VB-调用-C写的dll-再调用-dephi写的dephi,多绕一道湾.反正他以前就这么干过.
    与他一席话,胜过十年功,又觉得自己太渺小了.
    哈,这种套路心领神会还行,不一般人能干出来的.
      

  15.   

    7楼的代码哪个都试了,哪个都得挂,其实这两种方式一样,
    声明时如果参数为long,传入是就得是StrPtr(s);
    声明时如果参数为string,直接传入s就行,
      

  16.   

    那这么说 你在C里能调用这个DLL了?
      

  17.   

    17楼的代码我测过,也是崩在这一句
    r=checkuser(strOperId, ptr)
      

  18.   

        Dim strOperId As String
        Dim strMsg As String
        Dim a() As Byte
    以上是几个前辈的方案。我不赞同这些变量都定义成动态系类型。VB的动态系类型在内存中排列是很特殊的。我个人建议使用以下思路:
    dim strOperId(255) as byte 定义256字节空间
    dim strMsg(1023) as byte 定义1024字节空间
    这样定义,才是顺序排列数据,REDIM()、String()返回的都不是顺序排列的空间段,VB的动态系类型是VB的独有特性。发地址给DLL,DLL按照C惯例根本收不到顺序排列的数据,VB的动态系类型都包含描述符,只有VB自己读的出来,DLL那边收到的可能是类型描述符而不是真实数据的首地址,只有静态数组才是连续内存序列,不掺杂别的东西。
    推荐使用ASC函数,利用循环,把 "{F9AEE43D-E6B6-4787-84CC-FCB92F05A9DC}"这段字符装载到strOperId中,而不要使用能返回动态字符串或者动态数组的字符串处理函数。
    strOperId(0)=ASCB("{")
    strOperId(1)=ASCB("F")......依此类推,用循环法自动取字符,遇到中文,还要分别装载高8位和低8位。
    最后按照C语言惯例,要在字符串结尾加上0,strOperId(结尾ID)=0。
    C惯例中,在处理到0时,才结束。如果没有0,C系中的字符串处理程序指针会飞出数据段,后果不堪设想。我之所以频繁提到C惯例,是因为大多数程序是按照C惯例写的,甚至包括Dephi也是趋向C语言,而VB在处理字符串时,是个特例,VB甚至不理睬0的存在,它另有办法判断字符串长度。我支持以下VB声名方式,尤其是strOperId的类型,至于lpstrReturnMessage,前面先辈提醒可能是char**,我表示赞同,不过懒得进一步确认。至少lpstrOperID声明是对的。
    Public Declare Function checkuser Lib "zdtlmti.dll" _
        (ByVal lpstrOperID As Long, ByVal lpstrReturnMessage As Long) As Long以下是调用方法:传送了strOperId的首地址32位Long指针,指针所指向的空间遵循C惯例排列了全部信息,单位是8字节BYTE。至于strMsg,扔有待推敲。
    ....=checkuser( strOperId(0),strMsg(0))
      

  19.   

    不要因为懂点VC,就认为知道了C的全部。
      

  20.   

    宝兰德公司(现在是SUN)在指针处理方法上并不和VC穿一条裤子。不过还是接受32楼高手批评,我确实没仔细看原帖就发表了自己的看法。不对之处,万请各位同行海涵。
      

  21.   

    终于弄明白是怎么回事了,原来的Dll调用初始化文.ini件找不到,这个.ini得放到和编译器vb6.exe同一个目录下才好使,放在工程文件下就找不到;其实这个问题前几天就就应该找到,不知大家有没有下载我发的[Dll测试.rar],里面的测试说明中的第5句:
    [5.修改了ClientConfig.ini中的[DB]下的配置,使其故意不对,然后运行编译后的[Dll测试.exe],错误和3一样,是不是说明在VB调试环境下Dll没有读取到ClientConfig.ini的内容?],
    其实真就是VB调试环境下Dll没有读取到ClientConfig.ini的内容,就是因为一调试就崩溃,没有任何有用的提示,所以一直没想到;
    根本没有大家说的指什之类的问题,怎么测试都好使,17楼的方法试了也好使:
    1.声明时参数为string,直接传入str即可,
    2.声明时能数为long,传入StrPtr(str)也行
    我相信大家遇到的VB调试dll时崩溃的问题,如果dll本身需要初始化,大多是这个dll找不到外部文件导致.
    特别感谢这些天各楼层弟兄的顶力帮助,祝大家国庆快乐!