1,100
社区成员




VC编译的DLL有多种调用方式:__stdcall,__cdecl,__fastcall等,但是PB 可以调用的dll在C++里必须是__stdcall。而且,PB比较方便实用的传参类型也就string 对 char* ,long 对 int ,C++里不少类型PB没法传(我不会,呃)。
网上C++的各种资源很多,大多数编译好的DLL不是__stdcall的,于是PB就是调用不了。因此借用VC++,做一个DLL调用其它C++的资源,然后开放出PB可以调用的__stdcall的函数接口,成为PBer的无奈选择。最近有个事情恰好需要调用别家提供的DLL,于是尝试使用微软的Visual Studio 2022做了一遍,现在把过程写一下,方便后来人。
系统配置:
windows10 家庭版 64位
PB12.5 (32位)
一、从Microsoft Store安装Visual Studio Community 2022 ,社区版,免费的。安装之。
安装下载时间不短,要等一会。
二、 在vs2022【开始使用】处,点【创建新项目】
滚动条拉到最下面,【具有导出项的(DLL)动态链接库】,下一步
这里举例,创建项目名为:aaa
三、把需要调用的DLL相关的资源加入
在右边的 解决方案aaa下,右键点击【头文件】标签,再点击【添加】,【现有项】,选择需要调用DLL的头文件(*.h),加入头文件的列表。
我这个头文件里,有这个函数需要给PB调用:
EXTERN_API LONG WINAPI Ecode2pic_PB(
const void* const pCodeData,
int nDataLen,
const TCHAR* pszImageFile
);
四、编写给PB调用的API函数
在右边的解决方案aaa下,【源文件】下点击【aaa.cpp】,去掉系统默认给出的示例,#include的留着。
然后,加入自己的代码,开发函数去调用需要调用的资源。
这里C语言里的int类型,对应PB里面的long型。char* 对应 ref string 。
extern "C"
{
_declspec(dllexport) int add(int a ,int b) //这是一个做加法的测试函数,无用,可删
{
int c;
c = a + b;
return c;
}
_declspec(dllexport) int Ecode2pic_PB(char* codedata, char* picfilename) //这是传入数据codedata生成一个二维码图片picfilename的函数
{
long len;
len = strlen(codedata) ; //获取传入数据的长度
int ret = 0;
ret = Ecode2pic((const void*)codedata, len, picfilename); //调用在另一个DLL里无法被PB直接调用的函数
return ret;
}
}
我这里简化了函数的参数,原来需要传入codedata字符串长度,我给PB的函数里省略了,不用传长度,直接获取长度不就行了?
另外,从PB传入的是char*,传给另一个DLL里的函数要求是 const void* const ,这个不知道怎么转换,于是请【文心一言】帮了一把,文心一言给出了函数调用代码 : Ecode2pic((const void*)codedata, len, picfilename) ,经过测试好用!现在的AI大模型果然牛啊!
五、添加模块定义文件(*.def)
在右边的 解决方案aaa下,右键点击【源文件】,【添加】【新建项】,【Visual C++】【代码】【模块定义文件】
LIBRARY "ecode.dll"
EXPORTS
add
Ecode2pic_PB
六、一些关键配置项
在右边的 解决方案aaa下,aaa(项目)右键点击,最下面点【属性】。
PB是32位的,所以配置都要设置给win32用。模块定义文件,要选中上面新生成的def文件。
要设置本DLL给的API是用__stdcall方式调用的
要传递字符串,所以要与PB使用的字符集匹配。原来默认是unicode的,但是,我们DLL可能要给PB9及以前版本用的话,还是ANSI的更好吧,所以,我这里选了未设置,就是ANSI的。但是这样PB10以后版本的,在函数定义里要有 Alias for 子句。
七、编译
菜单下的一排工具栏里,要选 【Release】【X86】。PB是32位的,用X86的就是32位的。
然后,菜单里【生成】,【Build aaa】。
八、拷贝DLL
把编译出来的DLL和调用函数所在的DLL及依赖的DLL都要复制到PB代码所在文件夹里。
九、PB里面申明及调用
这个是PB里面的函数申明:
function long add(long a,long b) library "aaa.dll" Alias for "add;ANSI"
function long Ecode2pic_PB(ref string codedata, ref string picfilename) library "aaa.dll" Alias for "Ecode2pic_PB;ANSI"
下面是PB里面的函数调用 :
long c
int a=2
int b=3
c=add(a,b)
messagebox('',string(c))
long ret
string ls_pathfilename
string ls_data
ls_data=sle_data.text
ls_pathfilename=sle_pathfilename.text
ret=Ecode2pic_PB(ref ls_data,ref ls_pathfilename)
messagebox('ret',string(ret))
十、总结
现在大模型帮助下,能解决不少问题,难得一用的东西,也能拾起来试试了。