关于DLL封装(供其他开发工具调用vb,vc,pb..)(200分)

  • 主题发起人 主题发起人 martinwang
  • 开始时间 开始时间
M

martinwang

Unregistered / Unconfirmed
GUEST, unregistred user!
一DLL需要供其他开发工具调用:
函数声明:
  一
  int checkname(userinfo* usrInfo, workinfo* winfo, char* msg);//基于C++`
对应Delphi里这样声明:
type
userinfo = record
userid: integer;
username: array[0..20] of char; //pchar 用字符数组可否接收char*数据,即客户传入char* username这样的数据可否正常接收
userpassword: array[0..20] of char; //pchar 同上
end;
puserinfo = ^userinfo;
workinfo = record
workid: integer;
workaddr: array[0..140] of char;//同上
workexp: array[0..140] of char;//同上
end;
pworkinfo = ^workinfo;

function checkname(puInfo: puserinfo; pwkinfo: pworkinfo; msg: pchar): integer; stdcall;
1.这个函数对应Delphi里的声明是否有问题?
2.如果字符数组不能满足上面的要求,那么应该需要将char*(对应delphi里应该是pchar)转换成string或其他Delphi可以进
行操作的数据类型(比如转成另一个结构,进行网络传输)
3.在编写过程中还需注意些什么?

int getList(userinfo* usrInfo, usercj[] usrcj, char* msg) ;
对应Delphi里这样声明:
type
userinfo = record
userid: integer;
username: array[0..20] of char; //pchar 用字符数组可否接收char*数据,即客户传入char* username这样的数据可否正常接收
userpassword: array[0..20] of char; //pchar 同上
end;
puserinfo = ^userinfo;
usercj = record//用户成绩 举例
userid: integer;//传入
cjtype: array[0..20] of char;//同上 传出此值
cjname: array[0..20] of char;//同上 传出此值
cjDetail: double;// 传出
end;

function getList(puInfo: puserinfo; var usrcj: array of usercj; msg: pchar);
1.var usrcj: array of usercj 进来的值应该是引用,usercj[] usrcj c++里对数组,如同指针操作,这样声明对否??不对,应该如何做?
2.delphi dll中,对动态数组做为参数及返回值有一个规定即在工程单元里须加入shareMem单元,不知还有什么其他需要注意的地方?
3.同一里的2小点
由于这方面的经验不是很丰富,请各位大人提宝贵意见!!谢谢!!!
 
只一点,我 在用DELPHI做的DLL,用VC调的时候,如果是字符串的话一般都是这样定义结构体的,这样便于初始字符串大小.
userinfo = record
userid: integer;
username: pchar;
usernameLength : DWorD;
userpassword: pchar;
userpasswordLength: DWORD
end;

如果是指针数组的话,也就是c++里的char**的话.就用classes.pas里的
PPointerList = ^TPointerList;
TPointerList = array[0..MaxListSize - 1] of Pointer;
 
to _Murray 谢谢你的回复
只一点,我 在用DELPHI做的DLL,用VC调的时候,如果是字符串的话一般都是这样定义结构体的,这样便于初始字符串大小.
userinfo = record
userid: integer;
username: pchar;
usernameLength : DWorD;
userpassword: pchar;
userpasswordLength: DWORD
end;
============================
因为对客户公布的函数标准就是象我提到的那样,char* 型的数据应该可以用array[0..20] of char 这样的数组进行接收吧!!!??

如果是指针数组的话,也就是c++里的char**的话.就用classes.pas里的
PPointerList = ^TPointerList;
TPointerList = array[0..MaxListSize - 1] of Pointer;
=================================================
需要传入的参数是结构数组,而这个结构数组还可能不是定长的,动态数组,而delphi
dll对动态数组做为参数的导出函数好象有些问题,上网查资料而来!!
http://www.xue5.com/itedu/7679.html,如果象这上面说的,不能传递动态数组,该怎样解决!!!??
 
1.因为对客户公布的函数标准就是象我提到的那样,char* 型的数据应该可以用array[0..20] of char 这样的数组进行接收吧!!!??
这个当然可以.
2.需要传入的参数是结构数组,而这个结构数组还可能不是定长的,动态数组,而delphi
dll对动态数组做为参数的导出函数好象有些问题,上网查资料而来!!

如果是结构数组的话,你可以传结构数组指针呀.
至于你说的动态数组,那可以做一个尾标记,可以在VC里用WHILE读,读到结束标志为止.
这个我没用过,只是这么想的,我们传VC的数组都是固定的(便于初始化和最后释放),(一般谁申请的请释放)
 
用packed record会好些,按字节对齐
 
一、1、声明没问题
2、能满足要求
3、注意调用时如果声明指针,先分配内存,声明结构体的话直接传地址(这才是最重
要的部分)其实说白了,掌握了指针,你也就对这个东西没什么可怀疑的了

二、1、没用过数组,但这样认为,C++数组传过来也是一个数组首地址,你直接声明动态
数组即可,但调用时一定要先分配大小.如果用var在C++中,就等于是指针的指针
了,所以你所写应该不对(据理分析,没有测试)
2、动态数组与string等类型要shareMem,你完全可以用指针操作来避免它,你的程序
中没有要ShareMem单元的部分
3、同上了([:)])

以下两贴供参考:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3438484
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3423344
以上均为自己理解,也许有不对之处,也请指出!
 
to _Murray , uiit:
1.因为对客户公布的函数标准就是象我提到的那样,char* 型的数据应该可以用array[0..20] of char 这样的数组进行接收吧!!!??
这个当然可以.
=============================================
我试了一下,在Dll中定义一个简单的函数
type
userinfo = record
userid: integer;
username: array[0..20] of char;
userpassword: array[0..20] of char;
end;
puserinfo = ^userinfo;
procedure test(puInfo: puserInfo); stdcall;
begin
puinfo.userid := 111;
puinfo.username := 'testname';
puinfo.userpassword := 'testpwd';
end;

exports
test;

主调函数:
type
userinfo = record
userid: integer;
username: pchar;
userpassword: pchar;
end;
puserinfo = ^userinfo;
因为按照函数的定义为char* ,对应delphi应该为pchar,所以传入以上结构数据,由于手头
没有其他开发环境,不能对vb,vc,pb等测试

procedure mytest();
var
p: puserinfo;
begin
getmem(p, sizeof(userinfo));
test(p);
ShowMessage(p^.username + ' ' + p^.userpassword);//运行这句时报错
freemem(p);
end;
结论:
简单测试后,发现如果定义为char*的数据,用char[0..n] of char 这种方式接收可能有问题,不知道大家有什么意见!!!!


2.需要传入的参数是结构数组,而这个结构数组还可能不是定长的,动态数组,而delphi
dll对动态数组做为参数的导出函数好象有些问题,上网查资料而来!!

如果是结构数组的话,你可以传结构数组指针呀.
至于你说的动态数组,那可以做一个尾标记,可以在VC里用WHILE读,读到结束标志为止.
这个我没用过,只是这么想的,我们传VC的数组都是固定的(便于初始化和最后释放),(一般谁申请的请释放)

=============================================================
首先说一下,下面这个函数
int getList(userinfo* usrInfo, usercj[] usrcj, char* msg);
由于c++里的数组操作,等同于指针,即知道首地址后,通过指针对其操作,c++忘记了许多,不知道有没有错!!
上面的函数,对应delphi里应该如何写???
function getList(puInfo: puserinfo; var usrcj: array of usercj; msg: pchar);
对应该此函数有何问题??
今天进行了一下测试
调用端:
function getList(puInfo: puserinfo; usrcj: array of usercj{此处去掉var}; msg: pchar): integer; stdcall; extenal 'test.dll';
如果调用的Dll中的
function getList(puInfo: puserinfo; var usrcj: array of usercj; msg: pchar): integer;

结果还是可以把usrcj的值返回给调用端(传递的地址);
请大家多提一下这方面的意见,谢谢!!
 
1、老实话,你还没理解指针,与动态库什么没有关系,俺的两个帖子你应该好好看看
type
userinfo = record
userid: integer;
username: pchar;
userpassword: pchar;
end;
你这个类型和声明类型不一致,分配内存时它给你分配内存为多少,你发现没有
它给pchar分配的是一个指针 4byte,这个指针还仅仅是用来存放20byte的首址的
username: array[0..20] of char;
而这里需要用20个byte,怎么可能正确?
调用时候照样这么写
userinfo = record
userid: integer;
username: array[0..20] of char;
userpassword: array[0..20] of char;
end;
直接定义
var
usr: userinfo;
begin
test(@usr);
....
end;
即可
2、如果是定长数组,直接传数组,更好办,反正都是传首地址;应该这样就可以
由于c++里的数组操作,等同于指针,即知道首地址后,通过指针对其操作,没有错
function getList(puInfo: puserinfo; usrcj: array of usercj; msg: pchar);
这样的话,传过来的就是数组首地址,usrcj就是数组的首地址,操作直接对数组操作
等于你拿着没柄的锅炒菜
至于加var应该是这样工作
这里等于又声明了一个变量(指针变量吧)usrcj,把数组的首地址放在这个变量中,故也可以调用
现在你给锅加了柄,而你炒完菜又把柄给去了,操纵的是同一个(锅)数组,所以说这里应该是没什么影响

不知道我说清楚没?
 
to uiit:
1 你说的应该没错,可能我理解的有问题,那么在c++里的char* 类型,对应delphi里的pchar,那么delphi在接收数据的时候必要用pchar去对应,不可以用char[0..20] of char 这种定长的数组对应char*!!!(char* 的实质是char[]不定长度的字符数组!)应该是可以这样理解吧?如果是这样的话,我需要用pchar接收char* ,而我需要的是char[0..20] of char这样类型的数据,这就需要转换!!对否?
2 int getList(userinfo* usrInfo, usercj[] usrcj, char* msg);
先简单来说
function getList(puInfo: puserinfo; var usrcj: array of usercj; msg: pchar): integer;
这样的函数对应关系应该可以满足程序的需要吧??定义应该是正确的吧,usrcj为record不是指针!!能保证传入的usrcj里对应的某些值修改后,经过getlist成功返回主调程序中。
谢谢!!!!
 
http://www.delphibbs.com/delphibbs/dispq.asp?lid=1947206
 
1、不是你理解有问题,而是你根本没理解,对应不对应有关系吗?那样只是硬套一个规则
而已,虽然不能说不正确。你从本质上理解,指针传过来时地址,所以char *, PChar传
过来的是统一类型的地址。只要你传过来的是地址,怎么不可以用,你把数组收地址传
过来接受,有何不可?不需要转换。
2、满足要求,我知道不是指针,但在这里就可以理解为指针,有何不可?一个存放首地址
的变量,怎么不可以理解为指针,只能说Delphi的处理机制在这里其实更像一个引用了
他不需要靠指针那样来访问数据。
3、老大,拜托是你多试试再说话,你给俺的那个帖子有什么?不过就是按指针来存放数据
而已,我给你写的上面是按结构体来的,那样声明的时候已经给你分配了内存,不需要
你再getmem()了。如果你非要传个PChar, 你确定你要有地方存放它所指向的数据。

三篇下来说了这么多,应该该说的都说清楚了,理解不理解靠试,不是靠嘴
 
to uiit:
昨天弄的太晚了,没做一些测试!!!今天做了一下测试,
dll端:
unit untExport;
interface
type
userinfo = record
userid: integer;
username: array[0..20] of char; //pchar 用字符数组可否接收char*数据,即客户传入char* username这样的数据可否正常接收
userpassword: array[0..20] of char; //pchar 同上
end;
puserinfo = ^userinfo;
workinfo = record
workid: integer;
workaddr: array[0..140] of char;//同上
workexp: array[0..140] of char;//同上
end;
pworkinfo = ^workinfo;
procedure testp(pusrInfo: puserinfo); stdcall;
procedure testList(var info: array of workinfo); stdcall;
procedure testListp(pinfo: pworkinfo; itemcount: integer); stdcall;
implementation
procedure testp(pusrInfo: puserinfo);
begin
pusrInfo.userid := 1;
pusrInfo.username := 'testname';
pusrInfo.userpassword := 'testpwd';
end;

procedure testList(var info: array of workinfo);
var
i: integer;
begin
for i := 0 to High(info) do
begin
info.workaddr := 'testaddr';
info.workexp := 'testexp';
end;
end;

procedure testListp(pinfo: pworkinfo; itemcount: integer); stdcall;
var
i: integer;
begin
for i := 0 to itemcount - 1 do
begin
pinfo.workaddr := 'testaddr';
pinfo.workexp := 'testexp';
Inc(pinfo);
end;
end;
end.
调用端:



unit untMain;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
userinfo = record
userid: integer;
username: array[0..20] of char; //pchar 用字符数组可否接收char*数据,即客户传入char* username这样的数据可否正常接收
userpassword: array[0..20] of char; //pchar 同上
end;
puserinfo = ^userinfo;
workinfo = record
workid: integer;
workaddr: array[0..140] of char;//同上
workexp: array[0..140] of char;//同上
end;
pworkinfo = ^workinfo;
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
procedure testp(pusrInfo: puserinfo); stdcall ;external 'test.dll';
procedure testList(info: array of workinfo); stdcall ;external 'test.dll';
procedure testListp(pinfo: pworkinfo; itemcount: integer); stdcall;external 'test.dll';
var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
info: userinfo;
begin
testp(@info);
Memo1.Lines.Add(info.username + ' ' + info.userpassword);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
info: array of workinfo;
i: integer;
begin
setlength(info, 2);
testList(info);
for i := 0 to high(info) do
begin
Memo1.Lines.Add(info.workaddr + ' ' + info.workexp);
end;
end;

procedure TForm1.Button3Click(Sender: TObject);
var
info: array[0..1] of workinfo;
i: integer;
begin
// setLength(info, 2);//动态数组时有问题
testListp(@info, 2);
for i := 0 to high(info) do
begin
Memo1.Lines.Add(info.workaddr + ' ' + info.workexp);
end;
end;

end.
testlist, testlistp的执行效果是一样的!!!以前对指针的一些知识好久不用了,可能也是当时理解的不好!!!通过这个也复习了了一下指针操作!接受你给的一些意见及一些批评!!!谢谢!!在这种跨平台操作时还需要注意什么???再次感谢
 
嘿,看楼主这么辛苦的确实是试了!
那就在提醒你一点
// setLength(info, 2); //动态数组时有问题
testListp(@info, 2);
动态数组中@info只是这个这个指向这个数组的指针(嘿,你可能有要说我不该说它指针,动态数组嘛,就是指针)info的地址,而固定数组则不是,数组名就是数据首地址
而@info[0]还是才是数据首地址。
汗!这片帖子俺从动态库扯到指针还要扯到动态数组还要扯什么呢...
跨平台,也指跨开发平台?还要注意什么?这个好像经验不多,也说不上来吧
总之就是像DLL这样的东西,如果输出数据,多用指针,不要用只有单方面支持的东西
至于输出对象之类,Delphi和C++对象机制不同的话,估计是行不通(没有拿来试,俺其实也是个动嘴不动手的家伙[:)])
好了,此贴俺的答复到此为止(因为俺只知道这么多了)
如有错误遗漏,能告诉俺最好~~~
 
to uiit:
嘿,看楼主这么辛苦的确实是试了!
那就在提醒你一点
// setLength(info, 2); //动态数组时有问题
testListp(@info, 2);
动态数组中@info只是这个这个指向这个数组的指针(嘿,你可能有要说我不该说它指针,动态数组嘛,就是指针)info的地址,而固定数组则不是,数组名就是数据首地址
而@info[0]还是才是数据首地址。

嗯,根据你把说的,做了一个改动,是这个原因,当是动态数据时,@info[0]为首地址!!!
谢谢你的回复!!!!看其他人还有什么意见!!!!
 
多人接受答案了。
 

Similar threads

后退
顶部