VC调用delphi编写的dll时传出参数的问题 ( 积分: 200 )

  • 主题发起人 峻祁连
  • 开始时间

峻祁连

Unregistered / Unconfirmed
GUEST, unregistred user!
用VC调用delphi写的dll,想从dll里传出参数供VC调用,可结果发现没有传递出去,不知道是什么问题,VC我不太懂,大家看看哪儿有问题?

delphi写的dll代码如下
//输出函数
function GetEmployeeUser(out userId:pchar;out userName:pchar):integer;stdcall;
begin
try
frmInnerEmployee := TfrmInnerEmployee.Create(application);

if frmInnerEmployee.ShowModal=mrOK then begin
//test---在这里测试,改变要传出参数的值。
userId:='0';
userName:='testuser';
//test---
end;

result := 0;
except
on e : Exception do begin
showmessage(e.Message);
frmInnerEmployee := nil;
result := -1;
end;
end;

end;


VC的调用代码:
void CDllCallerDlg::OnBtnGetemployee()
{
typedef int (CALLBACK* LPFNDLLFUNC1)(CString userId,CString userName);
HINSTANCE hDLL
// Handle to DLL
LPFNDLLFUNC1 lpfnDllFunc1
// Function pointer

hDLL = LoadLibrary("YCCrm.dll");
if (hDLL != NULL)
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,
"GetEmployeeUser");
if (!lpfnDllFunc1)
{
// handle the error
FreeLibrary(hDLL)

return;
}
else
{
// call the function
//int userId = 1;
char userId[255]="22";
char userName[255];
int result = lpfnDllFunc1(userId,userName);//调用该dll函数
AfxMessageBox(userId);
if(result<0) AfxMessageBox(&quot;操作失败!&quot;);
}
}

FreeLibrary(hDLL);


}
 
用VC调用delphi写的dll,想从dll里传出参数供VC调用,可结果发现没有传递出去,不知道是什么问题,VC我不太懂,大家看看哪儿有问题?

delphi写的dll代码如下
//输出函数
function GetEmployeeUser(out userId:pchar;out userName:pchar):integer;stdcall;
begin
try
frmInnerEmployee := TfrmInnerEmployee.Create(application);

if frmInnerEmployee.ShowModal=mrOK then begin
//test---在这里测试,改变要传出参数的值。
userId:='0';
userName:='testuser';
//test---
end;

result := 0;
except
on e : Exception do begin
showmessage(e.Message);
frmInnerEmployee := nil;
result := -1;
end;
end;

end;


VC的调用代码:
void CDllCallerDlg::OnBtnGetemployee()
{
typedef int (CALLBACK* LPFNDLLFUNC1)(CString userId,CString userName);
HINSTANCE hDLL
// Handle to DLL
LPFNDLLFUNC1 lpfnDllFunc1
// Function pointer

hDLL = LoadLibrary(&quot;YCCrm.dll&quot;);
if (hDLL != NULL)
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL,
&quot;GetEmployeeUser&quot;);
if (!lpfnDllFunc1)
{
// handle the error
FreeLibrary(hDLL)

return;
}
else
{
// call the function
//int userId = 1;
char userId[255]=&quot;22&quot;;
char userName[255];
int result = lpfnDllFunc1(userId,userName);//调用该dll函数
AfxMessageBox(userId);
if(result<0) AfxMessageBox(&quot;操作失败!&quot;);
}
}

FreeLibrary(hDLL);


}
 
userId:='0';
userName:='testuser';
PChar类型的变量,不能这么赋值吧?
应该使用StrCopy吧
 
用StrCopy时会发生下面的错误,

Access violation at address 00C394E9 in module 'YCCrm.dll'. Read of address 00000030

------
是不是不能访问VC主程序里定义的内存空间啊?
 
把Out修饰符去掉
然后用StrPCopy试试看
手头上没有Delphi,否则帮你调试一下
 
基本常识.哪有这么传递字符串的.
看看API的字符串传递就知道了.
方案1.如果调用方知道最大长度,应该是PChar,Len内存由调用方申请和释放.
方案2.不能确定长度的时候PChar,var Len由被调用方用API申请内存返回内存和长度,调用方释放内存.
 
参考WINAPI的调用规则
比如一个GetWindowText函数,它是需要调用者分配PCHAR的内存空间,并告诉被调者空间的长度,然后被调者会往里面写数据,但不会超过调用者分配的长度,这样调用者负责分配/释放空间,而被调用者不用管.
尽量不要在不同的角色里分配/释放内存
 
//typedef int (CALLBACK* LPFNDLLFUNC1)(CString userId,CString userName);
delphi里面是pchar,vc里面是cstring,这样能行么?一个是简单类型指针,一个是MFC的类,vc这边的声明当然也应该是pchar才对啊。
 
哦,对了,忘了说
typedef int (CALLBACK* LPFNDLLFUNC1)(char* userId,char* userName);
是这样的
 
主要是你的调用方式不对,字符串问题还是次要
VC中:
int (* xFun ) (char* userId, char* userName)

xFun = ( int (*) ( char *, char *) )GetProcAddress(hDLL, &quot;GetEmployeeUser&quot;)

Delphi中

function GetEmployeeUser(userId:pchar;userName:pchar):integer;cdecl;
exports
GetEmployeeUser name 'GetEmployeeUser';

我测试过了,这样没问题
 
把代码帖全了吧
vc:
void CHahaDlg::OnOK()
{
HINSTANCE hDLL
// Handle to DLL
hDLL = LoadLibrary(&quot;YourDll.dll&quot;);

if (hDLL != NULL)
{
int (* xFun ) (char* userId, char* userName)

xFun = ( int (*) ( char *, char *) )GetProcAddress(hDLL, &quot;GetEmployeeUser&quot;)


if (!xFun)
{
// handle the error
FreeLibrary(hDLL)

return;
}
else
{
// call the function
// int userId = 1;
char userId[255]=&quot;22&quot;;
char userName[255];
int result= xFun(userId,userName);//调用该dll函数
AfxMessageBox(userId);
if(result<0) AfxMessageBox(&quot;操作失败!&quot;);
}
}

FreeLibrary(hDLL);

//CDialog::OnOK();
}

delphi:
unit YourUnit;
interface
uses
ExtCtrls, Classes, SysUtils, Types;

function GetEmployeeUser(userId:pchar;userName:pchar):integer;cdecl;
exports
GetEmployeeUser name 'GetEmployeeUser';

implementation

function GetEmployeeUser(userId:pchar;userName:pchar):integer;
begin
userid[1] := '0';
username[2] := '0';
result := 0;
end;
 
对不起,贴错了,下面的正确
双方都使用cdecl或者都使用stdcall,vc默认是cdecl,delphi默认是stdcall,所以至少有一方要强制改变一下,下面例子是delphi变成cdecl:
把代码帖全了吧
vc:
void CHahaDlg::OnOK()
{
HINSTANCE hDLL
// Handle to DLL
hDLL = LoadLibrary(&quot;YourDll.dll&quot;);

if (hDLL != NULL)
{
int (* xFun ) (char* userId, char* userName)

xFun = ( int (*) ( char *, char *) )GetProcAddress(hDLL, &quot;GetEmployeeUser&quot;)


if (!xFun)
{
// handle the error
FreeLibrary(hDLL)

return;
}
else
{
// call the function
// int userId = 1;
char userId[255]=&quot;22&quot;;
char userName[255];
int result= xFun(userId,userName);//调用该dll函数
AfxMessageBox(userId);
if(result<0) AfxMessageBox(&quot;操作失败!&quot;);
}
}

FreeLibrary(hDLL);

//CDialog::OnOK();
}

delphi:
unit YourUnit;
interface
uses
ExtCtrls, Classes, SysUtils, Types;

function GetEmployeeUser(userId:pchar;userName:pchar):integer;cdecl;
exports
GetEmployeeUser name 'GetEmployeeUser';

implementation

function GetEmployeeUser(userId:pchar;userName:pchar):integer;
begin
userid[1] := '0';
username[2] := '0';
result := 0;
end;
 
看不出有什么问题,用delphi写个程序调用这个dll试试有没问题
 
楼主为什么要用 out 啊, out 和 var 相似
 
现在用c#多些,受c#影响了,out 换成 var了
 
谢谢wanpeng:
不过
userid[1] := '0';
username[2] := '0';
==========

安装这种方式传一个字符出去没问题,可我想传一个字符串出去,难道要作循环?有没有更直接一点的办法?
 
strcopy(username,'jaj');
 
你如果想用string:
var
jj: String;
begin
jj := 'lll';
strcopy(username,PChar(jj));
 
好了,谢谢wanpeng

真是奇怪,我开始时用
strcopy(username,'jaj')

试了好多次都不行,

后来干脆就像你说的那个先定义一个string变量
var
jj: String;
begin
jj := 'lll';
strcopy(username,PChar(jj))


这样就可以了。^_^

能讲讲道理吗?
 
我2种方式都可以啊,不知道你为什么不行:(
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
804
import
I
顶部