VB6 动态调用标准dll,返回乱码并转换为正确结果问题。

tan126tan 2014-05-25 11:35:43
如题: 我有一些标准dll文件,,想在vb6 中动态载入,并取得正确返回值,并进行处理。
在网上找到了一个可以返回字符串的方法,但返回的是乱码,用 CopyMemory 进行了转换,但总崩溃,不知道原因何在,所以,请各位大哥、大嫂、大神们给指点指点,谢谢。
QQ: 2574155801
我不知道怎么上传附件。可以加我Q给你传一下。谢了各位大神。
头一次发贴,就没看 见在哪设置分数,如果问题解决了,我会多加些分数的。
...全文
844 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
PctGL 2014-06-03
  • 打赏
  • 举报
回复
所谓的动态调用API有什么意义。。。。
赵4老师 2014-05-29
  • 打赏
  • 举报
回复
不要低估操作系统文件处理的智商。 谁说文件一定要保存在磁盘上?保存在RamDisk上不行吗? 谁说文件一定保存在本地?映射网络驱动器不行吗? 无profiler不要谈效率!!尤其在这个云计算、虚拟机、模拟器、CUDA、多核 、多级cache、指令流水线、多种存储介质、……满天飞的时代!
舉杯邀明月 2014-05-28
  • 打赏
  • 举报
回复
即使是“跨开发环境”,要完成数据的“交换/传送”,也没必要借助于磁盘文件。
1.通过外设来处理,严重影响程序运行速度。
你这种能借助磁盘文件能完成的,都可以通过内存数据完成。(极大量的数据除外,这种情况一般只有在下载文件时才出现)
2. 使用到的dll,一般都是第三方的dll。其“数据传送方法”都是确定了的(基本上都是通过内存),你不可能让别人重新发布一个用磁盘文件交换数据的吧!
3. 如果dll是“自己的”,那多数时候都不存在“跨开发环境”、“A语言B语言”的问题了,甚至DLL都用不着了,全部代码整合在一个项目中。这时更用不着“磁盘文件来交换数据”。

假设一个如下的应用场景,恐怕“磁盘交换”就很不合理:
某专家研究了一个算法(DLL发布),可用于股票(或外汇)分析,指导投资者的交易和决策,当然这个“指导”还是“仅供参考”。要求输入“实时行情变化数据”(可能有几百个,也可能有几万甚至更多,函数接口有另一个参数指示数据量)、输出图表的HWND(当然这个是Form的,还是PictureBox的,决定于调用者),投资者通过“观看”这个图表(比如类似烛状图、K线图)的变化,决定自己的股票或外汇的买卖交易。
“实时行情数据”肯定是自己的程序负责采集、记录(具体是通过Web,还是交易平台提供数据通讯,这儿不用管),比如2秒采集一次,或是5秒采集一次。随着时间推移,数据量肯定逐渐增加(程序中有必要时,可以限制最大数据量),积累一定量的数据后,就可调用DLL中的函数进行分析,分析结果以图表模式绘制到指定的对象(hWnd标识)中。
你想想,这个“数据交换过程”,如果通过磁盘文件来做:
调用者把大量的数据写进磁盘……
被调用的过程又去从磁盘读数据……
分析结果,生成图片文档,写进磁盘……
读图片文件,把图像绘制出来……
如此反复~~~(因为肯定不是只分析一次,而是不停的采集、接着又来一轮分析)
你不觉得很别扭、运行效率很低吗????
舉杯邀明月 2014-05-28
  • 打赏
  • 举报
回复
即使是“跨开发环境”,要完成数据的“交换/传送”,也没必要借助于磁盘文件。
1.通过外设来处理,严重影响程序运行速度。
你这种能借助磁盘文件能完成的,都可以通过内存数据完成。(极大量的数据除外,这种情况一般只有在下载文件时才出现)
2. 使用到的dll,一般都是第三方的dll。其“数据传送方法”都是确定了的(基本上都是通过内存),你不可能让别人重新发布一个用磁盘文件交换数据的吧!
3. 如果dll是“自己的”,那多数时候都不存在“跨开发环境”
舉杯邀明月 2014-05-28
  • 打赏
  • 举报
回复
即使是“跨开发环境”,要完成数据的“交换/传送”,也没必要借助于磁盘文件。
1.通过外设来处理,严重影响程序运行速度。
你这种能借助磁盘文件能完成的,都可以通过内存数据完成。(极大量的数据除外,这种情况一般只有在下载文件时才出现)
2. 使用到的dll,一般都是第三方的dll。其“数据传送方法”都是确定了的(基本上都是通过内存),你不可能让别人重新发布一个用磁盘文件交换数据的吧!
3. 如果dll是“自己的”,那多数时候都不存在“跨开发环境”
赵4老师 2014-05-28
  • 打赏
  • 举报
回复
引用 23 楼 Chen8013 的回复:
[quote=引用 22 楼 zhao4zhong1 的回复:] 不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如: A将请求数据写到文件a.txt,写完后改名为aa.txt B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,改名为bb.txt A发现bb.txt存在时,读取其内容,读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢?
你不觉得:你这种回复让人很恶心啊????? [/quote] 你不觉得,这个回复可以解决所有跨开发环境问题吗?
舉杯邀明月 2014-05-27
  • 打赏
  • 举报
回复
引用 22 楼 zhao4zhong1 的回复:
不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如: A将请求数据写到文件a.txt,写完后改名为aa.txt B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,改名为bb.txt A发现bb.txt存在时,读取其内容,读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢?
你不觉得:你这种回复让人很恶心啊?????
赵4老师 2014-05-26
  • 打赏
  • 举报
回复
不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如: A将请求数据写到文件a.txt,写完后改名为aa.txt B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,改名为bb.txt A发现bb.txt存在时,读取其内容,读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢?
tan126tan 2014-05-25
  • 打赏
  • 举报
回复
还有就是返回的这个乱码,不能直接进行赋值给string变量(提示溢出),也不能用strconv进行转换(也提示溢出)
tan126tan 2014-05-25
  • 打赏
  • 举报
回复
但是,,就是不知道如何进行 转换,看了 <<在VB6中用CopyMemory拷贝字符串的种种猫腻>> 按照这个也使用了,但就是不成,不知道问题所在。
tan126tan 2014-05-25
  • 打赏
  • 举报
回复
Option Explicit
'调用 标准 DLL 中函数,并返回值给调用者
Private Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" (ByVal dest As Any, ByVal numbytes As Long)

'功能:动态调用 标准 DLL 中函数,并取得返回值
'参数:
'   strPluginPathFileName: DLL 文件路径
'   strFunctionName:       DLL 中被调用函数名称
'   strArg1~strArg5:       DLL 中被调用函数的参数(此例子全为字符串类型)
'返回:字符串 (返回 标准 DLL 中函数的返回值)
Public Function GetPluginInfo(ByVal strPluginPathFileName As String, ByVal strFunctionName As String, Optional ByRef strArg1 As String = "", Optional ByRef strArg2 As String = "", Optional ByRef strArg3 As String = "", Optional ByRef strArg4 As String = "", Optional ByRef strArg5 As String = "") As String
    Dim hModule As Long     '模块句柄
    Dim pFunction  As Long  '函数地址
    Dim pContent As Long    '插件返回内容指针
    Dim tmpContent As String '临时存放取得的内容
    
'    On Error Resume Next
    hModule = LoadLibrary(strPluginPathFileName)
    pFunction = GetProcAddress(hModule, strFunctionName)
    Dim tmpinfo As New FunctionPtr
    Dim tmpFunction As Object
    If strArg1 = "" And strArg2 = "" And strArg3 = "" And strArg4 = "" And strArg5 = "" Then
        Set tmpFunction = tmpinfo.Create(pFunction, vbString)
        CopyMemory tmpContent, StrPtr(tmpFunction.Invoke()), 4
    Else
        Set tmpFunction = tmpinfo.Create(pFunction, vbString, vbString, vbString, vbString, vbString, vbString)
        CopyMemory tmpContent, StrPtr(tmpFunction.Invoke(strArg1, strArg2, strArg3, strArg4, strArg5)), 4
        Debug.Print tmpContent
    End If
    FreeLibrary hModule
    GetPluginInfo = tmpContent
    Set tmpinfo = Nothing
    Set tmpFunction = Nothing
End Function
舉杯邀明月 2014-05-25
  • 打赏
  • 举报
回复
乱码,应该是编码问题。
CopyMemory()后程序崩溃,是你未能正确应用这个API(主要是参数传递不对)。
舉杯邀明月 2014-05-25
  • 打赏
  • 举报
回复
引用 20 楼 yachong 的回复:
原来是slowgrace写的猫腻,很久没见她和清零来VB版了

真的啊?
发个链接,我看看她怎么写的。


她俩是很久没来过了。
yachong 2014-05-25
  • 打赏
  • 举报
回复
原来是slowgrace写的猫腻,很久没见她和清零来VB版了
舉杯邀明月 2014-05-25
  • 打赏
  • 举报
回复
你7楼发出来的链接,我中午和则才都试过,
都是说失效了。
应该说不是我手机的问题吧。

你在7楼说“ 方法和他的一模一样 ”,
对于你,我只能说:无代码,无真相!
舉杯邀明月 2014-05-25
  • 打赏
  • 举报
回复
从你12楼看出:你根本还没有明白字符串是怎么回事。
你在6楼说“试了,不成”,我只能怀疑你未能正确应用Copymemory()。
你之前一直在说“溢出”,而最终证明是内存溢出。
你要注意“溢出”,跟“内存溢出”是完全不同的概念!

你的图片,我看到了。
如果正如你图中那点代码,出现“内存溢出”了,
只能说明你的Invoke()函数有问题!!!
Strconv()是内置函数,难道你不怀疑自己的函数,
反而怀疑它来了?!
如果它有问题,别人早发现了,还轮得到你来发现啊!
你在16楼说了“ 返回的也没多长啊 ”,你也明白内存溢出是“太长了”,
为什么不在aaa=.....Invoke()之后,来句:
msgbox “字符串长度:” & len(aaa)
看看它到底是如你想的那样“没多长”,还是“非常之长”???

虽然没看到你的代码,但我可以肯定:
你未能正确应用copymemory(),
你的Invoke()函数肯定有严重错误!
tan126tan 2014-05-25
  • 打赏
  • 举报
回复


直接赋值 或 转换 就是这错误
tan126tan 2014-05-25
  • 打赏
  • 举报
回复
提示的就是 内存溢出 或 是 字符串空间溢出, 那就太长了撒,,但返回的也没多长啊问题是。
tan126tan 2014-05-25
  • 打赏
  • 举报
回复
嗯,用人少了,但还有人在用。 找了个人看了一下,说在他哪运行没有问题,也不崩溃,真奇怪,但我用就是不行 。
twtiqfn 2014-05-25
  • 打赏
  • 举报
回复
很少有人用VB了啊
加载更多回复(9)

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧