| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 开发工具 -> PB调用DLL的常见问题及处理方法 -> 正文阅读 |
|
[开发工具]PB调用DLL的常见问题及处理方法 |
PB调用DLL的常见问题及处理方法 首先,为方便描述,先假设有一个DLL文件,名称为 test.dll,里面有个函数叫test。 第一类:通用型标准DLL 1、调用约定问题。Windows系统的标准DLL,通常有2种调用约定,即__cdecl和__stdcall,__stdcall约定在.h文件中通常又定义为 WINAPI和CALLBACK。咱们的PB只能调用__stdcall约定的DLL,不能调用__cdecl约定的DLL。 ? 如果调用了__cdecl约定的函数,会报以上错误。关键是“specified argument type deffers from ….“,内容是给定的参数顺序与要求的不一样。 对于这两种约定的区别,有兴趣了解更多的,可以自行百度。 2、DLL依赖问题。有时因为test.dll还需要依赖其他DLL,导致调用失败。 ? 依赖的DLL找不到时,通常会报类似这样的错误,然而这个提示并不明确,所以比较难查。在群共享里可以下载 loaddll.exe这个小工具,使用也比较简单,和DLL放在同一个目录,然后进入控制台命令行,输入 loaddll test.dll,观察控制台输出 ? 如果是依赖问题,这里的错误号是126。可以通过百度搜索 “getlasterror 126”查找具体情况,如果是其错误号,搜索时使用其他错误号。 3、DLL路径搜索错误。这个错误通常常是DLL不在应用程序当前目录下造成的,错误截图同上。也许你会说“我肯定我的DLL就在程序目录下“,但请注意是”当前目录“,当前目录并不是只指应用程序目录,虽然初始时默认是应用程序目录。假设你的程序在d:\test目录,你使用 GetOpenFileName 函数选择了d:\document\work.txt,这时候,你的当前目录就是d:\document\,而这时的当前目录下当然找不到 test.dll了,你的test.dll在d:\test呢。这是许多PB程序员容易忽略的原因。解决方法通常有以下几种: (1)在调用GetOpenFileName GetSaveFileName等函数前,先GetCurrentDirector函数保存当前目录,完成后,再 ChangeDiredtory切换回原当前目录。 (2)假设你的程序在d:\test目录,你可以直接设置系统的PATH环境变量指向这个目录。当然这个给实施人员带来一些小不便。 (3)程序初始化时,使用系统函数BOOL SetEnvironmentVariable(LPCTSTR lpName,LPCTSTR lpValue)把程序所在目录添加到进程环境变量里去,让DLL可以被搜索到。一个更加智能的方案是使用 pbidea 提供的设置函数 ? 可以确保当前目录、当前目录下的子目录,以及指定的其他目录里存放的DLL都可以被 搜索到。 特别值得一提的是,使用oracle数据库时,它的客户端在连接时会改变当前路径。 4、各种函数声明错误。这种错误就比较复杂了,涉及面也比较广。 可以参考另一篇博客PowerBuilder中调用DLL参数类型_lxbin2003的博客-CSDN博客_powerbuilder调用dll,提升对DLL及函数的理解 ,从而正确声明和使用函数 。 特别注意,一般情况下声明函数时 library “test.dll”,而不是 system library “test.dll”,这里的”system”不是随便加的。只有按照PB特定写法的DLL才可以添加这个system关键字。如果对C/C++写PB可调用的DLL有兴趣的话,可以到群共享下载 ,看看 system library方式是如何实现的。 ? 5、函数使用错误。DLL函数都是按照C约定开放接口。我们知道C的指针,总是让人不得不打起十二分精神来对待。你认为PB里不涉及到指针,你就错了。比如test函数 function int test(string a1,ref string a2,long a3) library "test.dll" 这个函数的C原型是这样的: extern "C" __declspec(dllexport) int __stdcall test(char* a1, char* a2, int a3) PB里的string,对应到C的原因,实际上就是指针。如果是输入型参数倒也没太大问题,如果是输出型参数,那就必须要预分配足够的内存空间。通常PB里预分配空间,使用space函数。 String ls_a2 ls_a2 = space(10000) 这样 ls_a2 这个变量就有 10000个字符的空间,注意,如果 是PB10以上版本,它实际上有了20000个字符的空间,因为一个 unicode字符占用2个char空间。 如果没预分配内存,或者预分配内存大小不够,程序也许能运行一小会,但后面不知道会在什么位置莫名其妙崩溃。 6、DLL开发者错误。许多人临时需要某个功能,操起VC就开始写DLL,但也因为对c/c++掌握程度问题,会导致一些BUG,这些只能PB运行不正常时,自己排查规律,如果确定是DLL的原因,得找DLL开发人员处理了。 第二类:COM类DLL 曾经COM是非常热门的一个技术,它也是微软应用与操作系统捆绑的一个典范。然而,在PB中,其实并不建议使用COM方式的DLL。 目前COM方式的DLL,一个是历史遗留下来的古老应用,二是有些人图方便使用C#写DLL给PB用,三是有些PB版本(比如PB9)自己也支持写COM给其他应用使用。 COM方式的DLL,它首先需要注册,这个比较麻烦,在win7及以前版本中,还可以使用 run 方式进行自注册,但在WIN10及其后版本中,自注册就比较困难了,因为注册时需要管理员权限。一两台电脑注册COM可以接受,如果类似HIS这样的应用,一个医院动辄布署几百台电脑,需要一个一个去注册COM,那就呵呵了。尤其是C#写的COM,在不同操作系统上,可能依赖的.net framework还不一样,还需要安装这些额外的内容。 所以,建议PB尽量远离COM类的DLL。 第三类:PB自身的DLL 上面刚才提到PB有些本可以写COM。另外,PB自己的PBL也可以编译成DLL。如果是PB编译出来的DLL库,可以直接当作PBL一样添加到库列表中使用。如果给其他人提供PB的业务接口,这也不失为一个方案。只不过它有个限制:只能是同一个PB版本使用。 欢迎加入pbidea群,共同探讨PB技术。群号:624409252 ?? ??????????????????????????????大自在(QQ:781770213) ?????????????????????????????????? 2022/5/8 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 2:23:40- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |