dll的调用?(10分)

  • 主题发起人 主题发起人 chenchangliang
  • 开始时间 开始时间
C

chenchangliang

Unregistered / Unconfirmed
GUEST, unregistred user!
[?]我是个delphi的初学者,现请问:有个vc编写的dll,在程序里怎么调用?请不吝赐教!

 
procedure yourprocedure; external 'yourlib.dll';

function yourFunction(S: string): string; external 'yourlib.dll';
还可以动态调用:
tmphd:=loadlibrary('yourlib.dll');
getprocess(...);
freelibrary(...);
 
首先你先贴出那个VC写的DLL来看看
 
来自:tseug, 时间:2002-11-7 20:09:00, ID:1419991
----------------------------------------------------------------------
参考这个

时间:2002.07.12 于重庆

主题:VC与Delphi之间动态链接库互相调用

内容:


Delphi 调用VC的DLL


VC中DLL声名格式:

Extern “C” void __declspec(dllexport) __stdcall ShowMess(HWND hwnd, char* mess);

输出格式为:_ShowMess@8,“8”为函数参数字节数

为了避免名称分裂,可采用以下方法解决:

1.声明中不加__stdcall,采用VC默认格式__cdecl,但在Delphi中要注明调用格式为cdecl。

2.在VC工程中添加def文件,如:

LIBRARY

EXPORTS

ShowMess @1

则DLL中输出函数名称不分裂。


Delphi中调用格式:

Procedure ShowMess (h:HWND; mess:PChar); Stdcall;{Cdecl;} external LibName;

如无Stdcall或Cdecl声名,Delphi默认Register(FastCall)调用格式。


注意Delphi与VC的对齐格式不同,在VC中定义结构时要用以下格式:

#pragma pack(4)

//结构定义

#pragma pack()


常用工具:

TDump.exe-Delphi 4 和 C++ Builder 3 提供

Impdef.exe 和 Implib.exe - C++ Builder 3提供

DumpBin.exe-VC5.0提供

Lib.exe-VC5.0提供


VC调用Delphi的DLL


Delphi中的声名格式:

Function ShowDialog( hMainWnd:THandle; Msg:PChar ):integer; stdcall;

输出到Dll文件中时,名称不分裂。


VC中的调用格式:

extern "C" __declspec(dllimport) int __stdcall ShowDialog( HWND hwnd,char* Msg );

.如带有__stdcall,则要求Lib文件中对应函数名称分裂,可有以下步骤生成Lib文件:

.用Impdef.exe生成def文件,格式为:Impdef def文件名 dll文件名

.手工调制def文件参数,如ShowDialog改为ShowDialog@8

.用Lib.exe生成lib文件,格式为:Lib /def:def文件名

.如声名中无__stdcall,默认调用格式仍为stdcall,但不要求名称分裂,用以下批处理文件MkLib.bat可生成Lib文件:

@echo off

if %1.==. goto error

impdef %1.def %1.dll

lib /def:%1.def

goto end

:error

echo Usage: MkLib DllName

echo Note: Don't add extension ".dll" to parameter "DllName"

:end
 
vc里的dll(SMDDLL.dll)有这样的函数:
//初始化SMD:
//输入: ComPortName: 串口号
// CSCA: 短信中心号码
//输出: pID: 使用的模块标识
//返回: 1: 正确
// 0X80: 打开串口错误
// 0X81: 启动线程失败
// 0X82: 串口未连接设备
// 0X83: 串口未连接MODEM设备
// 0X84: 模块没有注册
// 0X180: SIM卡错误
// 0X181: 信号太差
// 0X182: SIM卡无法注册网络
// 0X183: 设置PDU模式失败
// 0X184: 设置短消息中心号码错误
// 0XF01: 打开的模块数目超过限制(6个)。
////////////////////////////////////////////////
int WINAPI SMDInit(int *pID,const char * ComPortName,const char * CSCA);

在delphi里这样申明对吗?
Function SMDInit(ID:Integer;ComPortName:Pchar;CSCA:Pchar):Integer;external 'SMDDLL.dll';
 
Function SMDInit(ID:Integer;ComPortName:Pchar;CSCA:Pchar):Integer;cdecl; external 'SMDDLL.dll';
~~~~~~
 
谢谢zw84611, 但我在加cdcel、stdcall或pascal时程序运行时都报access violation错误,
据编写此dll的vc人说他是用的时stdcall,所以我只有在不加cdcel、stdcall或pascal。
delphi里申明时编译通过,只是返回的值不是1,而是128(即0x80,但端口肯定没问题)
但此dll用vc、c++builder、powerbuiler、vb 调用都没问题。我实在没办法。
下面是我delphi里的源玛:(dll源码我没有)
delphi:
var
Form1: TForm1;
Rtn_Send,Id:Integer;
Mode_flag:Integer = 4;

implementation

{$R *.dfm}
//Function SMDInit(ID:Integer;ComPortName:Pchar ;CSCA:Pchar ):Integer;external 'e:/wt10/SMDDLL.dll';
Function SMDInit(ID:LongInt;ComPortName:LPCTSTR ;CSCA:LPCTSTR ):Integer;cdecl;external 'SMDDLL.dll';
Function SMDClose(ID:Integer):Integer;external 'SMDDLL.dll';
Function SMDSend(ID:Integer; DestAddress:String; buf:String; chMode:string;chID:String):Integer;external 'SMDDLL.dll';
Function SMDRec(ID:Integer;chaPhone:String; chaMessage:String):Integer;external 'SMDDLL.dll';
Function SMDGetReturn(ID:Integer;chID:String; phone:String; datetime:String;chReturn:String):Integer;external 'SMDDLL.dll';
Function SMDSetMode(ID:Integer;flag:Integer):Integer;stdcall;external 'SMDDLL.dll';

procedure TForm1.ComboBox1Change(Sender: TObject);
begin
if combobox1.text<>'' then
begin
edit1.Enabled:=true;
edit1.SetFocus;
edit2.Enabled:=True;
Memo1.Enabled:=True;
BitBtn1.Enabled:=True;
BitBtn2.Enabled:=True;
BitBtn3.Enabled:=True;
Timer1.Enabled:=False;
end;
end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
Mode_flag:=0;
if CheckBox1.checked then
Mode_flag:=Mode_flag + 1;
end;

procedure TForm1.CheckBox2Click(Sender: TObject);
begin
if CheckBox2.checked then
Mode_flag:=Mode_flag + 2;
end;

procedure TForm1.CheckBox3Click(Sender: TObject);
begin
if CheckBox3.checked then
Mode_flag:=Mode_flag + 4;
end;

procedure TForm1.BitBtn2Click(Sender: TObject);
Var
Rtn_Init,Rtn_Mode:Integer;
// Rtn_Init:Pchar;
chID,chMod:String;
s_com,s_center:String;
begin
//短信中心号码不能为空
If edit1.Text='' then
begin
MessageDlg('''短信中心号码''不能为空!',mtInformation,[mbOk],0);
edit1.SetFocus;
Application.Terminate;
end;

//被叫手机号不能为空
If edit2.text='' then
begin
MessageDlg('''被叫手机号''不能为空!',mtInformation,[mbOk],0);
edit2.SetFocus;
Application.Terminate;
end;

//短消息模式
If RadioButton1.checked then
chmod:='1'
Else If RadioButton2.checked then
chmod:='0'
Else If RadioButton3.checked then
chmod:='2';

//手机短信内容不能为空
If Memo1.text='' then
begin
memo1.SetFocus;
Application.Terminate;
end;

//设置短信收发程序属性
Rtn_Mode:=SMDSetMode(254,mode_flag);
If Rtn_Mode<>0 then
Messagedlg('输入的模块标识非法!',mtInformation,[mbOk],0);

//模块初始化
// MessageDlg(combobox1.Text,mtInformation,[mbOk],0);
// MessageDlg(Edit1.Text,mtInformation,[mbOk],0);
s_com:=combobox1.Text;
s_center:=Edit1.Text;
// Rtn_Init:=SMDInit( Id,'COM1','8613800551500');
Rtn_Init:=SMDInit( Id,Pchar(s_com),Pchar(s_center));
MessageDlg(inttostr(Rtn_Init),mtInformation,[mbOk],0);
// If Rtn_Init<>1 then
// begin
// MessageDlg('模块初始化失败!',mtInformation,[mbOk],0);
// Application.Terminate;
// end;

//设置短信收发程序属性
// Rtn_Mode:=SMDSetMode(Id,mode_flag);
// If Rtn_Mode<>0 then
// Messagedlg('输入的模块标识非法!',mtInformation,[mbOk],0);

//发送短消息
// Rtn_Send:=SMDSend(Id,edit2.Text,Memo1.Text,chMod,chID);
edit3.text:=inttostr(Rtn_Send);
end;

procedure TForm1.BitBtn3Click(Sender: TObject);
begin
if BitBtn3.Caption='开始接收' then
begin
BitBtn3.Caption:='停止接收';
BitBtn4.Enabled:=False;
timer1.enabled:=true;
//每隔5秒收一次短信
timer1.Interval:=5000;
// Rtn_Rec:=SMDRec(Id,chaPhone,chaMessage);
// Case Rtn_Rec of
// 0: MessageDlg('没有接收到信息',mtInformation,[mbOk],0);
// 1..4:MessageDlg(chaPhone+'#13'+'#10'+chaMessage,mtInformation,[mbOk],0);
// Else
// MessageDlg('接收短消息失败,失败号:'+inttostr(Rtn_Rec),mtInformation,[mbOk],0);
// end;
end
Else
begin
BitBtn3.Caption:='开始接收';
BitBtn4.Enabled:=True;
timer1.Enabled:=false;
End;

end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
Rtn_rec:Integer;
chaMessage,chaPhone:String;
begin
// Rtn_Rec:=SMDRec(Id,chaPhone,chaMessage);
Case Rtn_Rec of
0: MessageDlg('没有接收到信息',mtInformation,[mbOk],0);
1..4:MessageDlg(chaPhone+'#13'+'#10'+chaMessage,mtInformation,[mbOk],0);
Else
MessageDlg('接收短消息失败,失败号:'+inttostr(Rtn_Rec),mtInformation,[mbOk],0);
end;
end;

procedure TForm1.BitBtn1Click(Sender: TObject);
var
phone,chID,datetime,chReturn,s:string;
Rtn_Return:Integer;
begin
// Rtn_Return:=SMDGetReturn(Id,chId,phone,Datetime,chreturn);
If Rtn_Return=0 then
MessageDlg('无回执信息',mtInformation,[mbOk],0)
Else
begin
If chReturn='0' then
chReturn:='对方已经收到'
Else if chReturn='34' then
chReturn:='对方暂时不可达'
Else
chReturn:='对方号码无效';
s:='被叫号码:'+ phone+'#13'+'#10';
s:=s+'发送成功时返回的ID号:'+chID+'#13'+'#10';
s:=s+'收到回执的时间:'+datetime+'#13'+'#10';
s:=s+'回执的内容:'+chReturn;
MessageDlg(s,mtInformation,[mbOk],0);
end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//释放资源
// SMDClose(Id);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
buffer: array [0..255] of char;
FileToFind: string;
begin
GetWindowsDirectory(buffer, SizeOf(buffer));
FileToFind := FileSearch('SMDDLL.dll', GetCurrentDir + ';' + buffer);
if FileToFind = '' then
begin
ShowMessage('没有找到''SMDDLL.dll''文件。');
Application.Terminate;
end;

end;

procedure TForm1.BitBtn4Click(Sender: TObject);
begin
//释放资源
// SMDClose(Id);
// MessageDlg(inttostr(SMDClose(Id)),mtInformation,[mbOk],0);
Close;
end;


vc的函数:
#ifdef SMDDLL_EXPORTS
#define SMDDLL_API __declspec(dllexport)
#else
#define SMDDLL_API __declspec(dllimport)
#endif

#define ASCII_SET 0
#define CHINESE_SET 1
#define DATA_SET 2
#define MAXPHONE 20
#define SMD_VER 0x02080005

////////////////////////////////////////////////
//获取该DLL的版本号
//输入: 无
//输出: 无
//返回: SMD_VER
////////////////////////////////////////////////
unsigned int WINAPI SMDGetVer();

////////////////////////////////////////////////
//初始化SMD:
//输入: ComPortName: 串口号
// CSCA: 短信中心号码
//输出: pID: 使用的模块标识
//返回: 1: 正确
// 0X80: 打开串口错误
// 0X81: 启动线程失败
// 0X82: 串口未连接设备
// 0X83: 串口未连接MODEM设备
// 0X84: 模块没有注册
// 0X180: SIM卡错误
// 0X181: 信号太差
// 0X182: SIM卡无法注册网络
// 0X183: 设置PDU模式失败
// 0X184: 设置短消息中心号码错误
// 0XF01: 打开的模块数目超过限制(6个)。
////////////////////////////////////////////////
int WINAPI SMDInit(int *pID,const char * ComPortName,const char * CSCA);

////////////////////////////////////////////////
//关闭SMD:
//输入: ID:模块标识(在初始化中输出的pID中的值)
//返回: 0:
// 0xF01:输入的模块标识非法。
////////////////////////////////////////////////
int WINAPI SMDClose(int ID);

////////////////////////////////////////////////
//设置短信收发程序属性:
//输入: ID: 模块标识(在初始化中输出的pID中的值)
// 如果输入的ID为254,则表示设置所有模块的状态
// (在初始化模块前由于尚未生成ID,只有使用254来设置所有模块的属性)
// flag:
// 0x01: 进入调试模式(显示错误提示对话框)
// 0x02: 写错误日志
// 0x04: 是否提供短信回执
//返回:
// 0: 正常
// 0xF01: 输入的模块标识非法。
// 0xF02: 输入的模块标识非法。
//
//注 : flag提供的值可以相加,例如 0x03表示调试模式、写日志、不要回执
// 0x05表示调试、不写日志、要回执
////////////////////////////////////////////////
int WINAPI SMDSetMode(int ID,int flag);

////////////////////////////////////////////////
//发送短消息:
//输入: ID: 模块标识(在初始化中输出的pID中的值)
// DestAddress: 被叫号码
// buf: 待发送短信内容
// chMode: 发送的模式:0--西文,1--中文,2--数据
//输出:
// chID: 短信回执的索引号(发送成功时有效)
//返回: 1: 发送成功;
// 0: 发送错误;
// 2: 发送失败;
// 4: 内容中含有须过滤字符,发送失败;
// 9: 数据方式中信息超长(中西文方式下如果超长将被自动截取);
// 999: 发送信息未被接受;
// -2: 被叫号码超长(MAXPHONE),拦截;
// 0x80: 设置PDU模式指令发送错误
// 0x81: 设置PDU模式指令执行失败
// 0x82: 进入发送模式指令发送错误
// 0x83: 进入发送模式指令执行失败
// 0x84: 进入发送模式指令执行失败
// 0x85: 发送信息体指令发送错误
// 0x86: 发送信息体指令执行失败
// 0x87: 发送确认信息错误
// 0x88: 发送信息未成功
// 0xF01: 输入的模块标识非法。
////////////////////////////////////////////////
int WINAPI SMDSend(int ID,const char *DestAddress,const char *buf,char chMode,unsigned char * chID);

////////////////////////////////////////////////
//接收短消息:
//输入: ID: 模块标识(在初始化中输出的pID中的值)
// chaPhone: 存放主叫号码
// chaMessage: 存放接收到的信息
//返回: 0: 表示没有接收到信息;
// 1: 表示接收到一条西文信息;
// 2: 表示接收到一条中文信息;
// 3: 表示接收到一条数据信息;
// 4: 表示接收到一条未定义信息;
// 0x80: 发送读短信指令错误
// 0x81: 读短信指令执行失败
// 0x82: 读短信存储ID错误
// 0x83: 读短信PDU长度错误
// 0x84: 读短信PDU信息体错误
// 0x85: 读短信确认信息错误
// 0x86: 发送删除短信指令错误
// 0x87: 执行删除短信指令失败
// 0xF01: 输入的模块标识非法。
// 注意,原来的返回值:-1已经不再使用。
////////////////////////////////////////////////
int WINAPI SMDRec(int ID,char * chaPhone, char * chaMessage);


////////////////////////////////////////////////
//获取短信回执:
//输入:
// ID:模块标识(在初始化中输出的pID中的值)
//输出:
// phone:被叫号码;
// chID:发送成功时返回的ID号
// datetime:收到回执的时间
// chReturn:回执的内容
// 0:对方已经收到;
// 34:对方暂时不可达;
// 99:对方号码无效;
//返回:
// 0:无回执信息,输出参数无效;
// 1:有回执信息,输出参数有效;
// 0xF01:输入的模块标识非法。
////////////////////////////////////////////////
int WINAPI SMDGetReturn(int ID,unsigned char *chID,char *phone,char *datetime,unsigned char *chReturn);

//使用方法:
// 先调用SMDInit(pID,串口,短信中心号码)初始化程序
// 再调用SMDSend(ID,被叫手机,内容,模式,chID)发送短信,并在chID中获取回执标识
// 需要读取短信时调用SMDRec(ID,来电号码,内容)接收短信
// 可能需要使用单独的线程每隔一段时间(5秒)来读取一次短信
// 需要读取回执时调用SMDGetReturn(ID,回执标识,查询手机号码,datetime,回执),
// datetime中为回执时间。
// 程序结束时调用SMDClose(ID)释放资源。
//
// 在程序的任何地方可以调用SMDGetVer()函数来获得该DLL的版本号。
// 在调用过SMDInit之后且调用SMDClose之前,可以调用SMDSetMode函数设置该模块的属性
// 缺省的属性为不生成错误提示对话框、不记录错误日志、提供回执信息。

请大侠帮我看看!

 
上面的函数申明主要是对SMDInit初始化,因为SMDInit里的参数ID是输出值,没有正确的ID
后面的函数没办法调用所以后面的函数申明参数都没有改,应该位PChar型。
 
谢谢各位,问题解决了,申明应该为:
Function SMDInit(out ID:Integer;Const ComPortName:Pchar ;Const CSCA:Pchar ):Integer;stdcall;external 'SMDDLL.dll';
其中的ID为输出参数!
麻烦了!
 
后退
顶部