微信扫一扫 分享朋友圈

已有 171 人浏览分享

开启左侧

PB调用DLL出现问题及解决方法

[复制链接]
171 0
第一类:通用型标准DLL
1、调用约定问题。Windows系统的标准DLL,通常有2种调用约定,即__cdecl和__stdcall,__stdcall约定在.h文件中通常又定义为 WINAPI和CALLBACK。咱们的PB只能调用__stdcall约定的DLL,不能调用__cdecl约定的DLL。
image.png
如果调用了__cdecl约定的函数,会报以上错误。关键是“specified argument type deffers from ….“,内容是给定的参数顺序与要求的不一样。
对于这两种约定的区别,有兴趣了解更多的,可以自行百度。

2、DLL依赖问题。有时因为test.dll还需要依赖其他DLL,导致调用失败。

image.png
依赖的DLL找不到时,通常会报类似这样的错误,然而这个提示并不明确,所以比较难查。在群共享里可以下载 loaddll.exe这个小工具,使用也比较简单,和DLL放在同一个目录,然后进入控制台命令行,输入 loaddll test.dll,观察控制台输出
image.png

如果是依赖问题,这里的错误号是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 提供的设置函数

image.png
可以确保当前目录、当前目录下的子目录,以及指定的其他目录里存放的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开发人员处理了。

7、一个容易忽视的问题。PB是32位程序,与你运行的操作系统是不是64位没有关系。所以,如果人家提供给你的DLL里有32位和64位,请一定要记住:你使用它的32位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版本使用。



免责声明:
1,海欣资源网所发布的资源由网友上传和分享,不保证信息的正确性和完整性,且不对因信息的不正确或遗漏导致的任何损失或损害承担责任。
2,海欣资源网的资源来源于网友分享,仅限用于学习交流和测试研究目的,不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。
3,海欣资源网所发布的资源由网友上传和分享,版权争议与本站无关,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。
4,如果您喜欢,请支持正版,购买正版,得到更好的正版服务,如有侵权,请联系我们删除并予以真诚的道歉,联系方式邮箱 haixinst@qq.com
海欣资源-企业信息化分享平台。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

0

粉丝

27

主题
热度排行
回复排行
最新贴子

Archiver|手机版|海欣资源 ( 湘ICP备2021008090号-1 )|网站地图

GMT+8, 2022-12-9 12:49 , Gzip On, Redis On.

免责声明:本站所发布的资源和文章均来自网络,仅限用于学习交流和测试研究目的,不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。 本站信息来自网络,版权争议与本站无关,您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 如果您喜欢,请支持正版,购买正版,得到更好的正版服务,如有侵权,请联系我们删除并予以真诚的道歉。