線上訂房服務-台灣趴趴狗聯合訂房中心
發文 回覆 瀏覽次數:1954
推到 Plurk!
推到 Facebook!

如何轉換呼叫Dll要帶入的資料型態~

答題得分者是:Victor4022
ed_lin
一般會員


發表:1
回覆:8
積分:1
註冊:2011-11-03

發送簡訊給我
#1 引用回覆 回覆 發表時間:2011-11-03 15:01:47 IP:59.124.xxx.xxx 訂閱
這是呼叫某一個dll內函式內容
VfyPwd(nDevAddr,iPwd)

#define nDevAddr 0xffffffff
unsigned char iPwd[4]={0};

我有點疑問 unsigned char iPd[4] 要如何轉換成Delphi 的型態呢?
我先使用Byte,不過還是無法正確傳入值,
底下是我呼叫Dll的程式碼,請大家參考一下

[code delphi]
function fyPwd(aAddr: Integer; aPass: Byte): Integer; Stdcall; External 'APIE.dll';

procedure TForm1.BitBtn1Click(Sender: TObject);
var
i: Integer;
begin
i:=VfyPwd($ffffffff, 0);
ShowMessage(IntToStr(i));
end
[/code]


Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#2 引用回覆 回覆 發表時間:2011-11-04 06:43:17 IP:122.126.xxx.xxx 訂閱
要傳入字串到 dll function, 參數型態離不開 pointer 類的型別,
試試字元指標吧 -> PAnsiChar
需注意 password 格式為 Ansi/Wide (看你宣告 unsigned char[4], 假設是 Ansi..)

ed_lin
一般會員


發表:1
回覆:8
積分:1
註冊:2011-11-03

發送簡訊給我
#3 引用回覆 回覆 發表時間:2011-11-04 10:25:47 IP:59.124.xxx.xxx 訂閱
Dear Victor4022:

謝謝你的回答
我試著將程式碼改成如下, 還是得不到回應正確的值

function fyPwd(aAddr: Integer; iPassWord: Array of PAnsiChar): Integer; Stdcall; External 'APIE.dll';
procedure TForm1.BitBtn1Click(Sender: TObject);
var
i: Integer;
c: Array[0..4] of PAnsiChar;
begin
c[0]:='0';
c[1]:='0';
c[2]:='0';
c[3]:='0';
c[4]:='0';
i:=VfyPwd($ffffffff, c);
ShowMessage(IntToStr(i));
end



編輯記錄
ed_lin 重新編輯於 2011-11-03 20:26:38, 註解 無‧
ed_lin 重新編輯於 2011-11-03 20:27:05, 註解 無‧
ed_lin 重新編輯於 2011-11-03 20:27:32, 註解 程式碼版面錯誤‧
Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#4 引用回覆 回覆 發表時間:2011-11-05 01:27:18 IP:122.126.xxx.xxx 訂閱
您好,
1. 建議您先將 DLL export 的原型貼出來

2. 指標的部份, 例如像是下方使用某個加密 DLL 的 export function 宣告
(參數 1 ~ 3 為不同的字元指標, 參數 4 表示第三個參數的 BufferSize):

[code delphi]
var
MyEncryptDllTestFunc: function(lpszData: PAnsiChar; lpszKey: PAnsiChar;lpszBuffer: PAnsiChar; dwBufferSize: DWORD): DWORD; stdcall;
[/code]

後方使用宣告的程式則是:
[code delphi]
const
MY_BUFFER_SIZE = 512;
var
aBuffer: array [0..MY_BUFFER_SIZE - 1] of AnsiChar;
sData, sKey : String;
dwReturn : DWORD;
begin
sData := '想要被處理的字串';
sKey := 'testKey';
dwReturn := MyEncryptDllTestFunc(PAnsiChar(sData), PAnsiChar(sKey), @aBuffer, MY_BUFFER_SIZE);
...
...
...
end;
[/code]
ed_lin
一般會員


發表:1
回覆:8
積分:1
註冊:2011-11-03

發送簡訊給我
#5 引用回覆 回覆 發表時間:2011-11-05 19:59:08 IP:1.200.xxx.xxx 訂閱
Dear Victor4022:

謝謝您的回答,

Dll 是來自 VC 6.0, 這是硬體廠商提供,跟他請教過要如何呼叫裡面的function,
他提供了下列的內容,因為廠商對Delphi不熟,無法說明Delphi要如何呼叫
xxx.h
int WINAPI VfyPwd(int nAddr,unsigned char* pPassword);
參數
//#define nDevAddr 0xffffffff
//unsigned char iPwd[4]={0};

所以目前只能把我知道Delphi呼叫Dll的方式都套進去Try,唯一比較不清楚的是,
廠商說明iPwd是4個0000, unsigned char = Delphi Byte型態,
但是我試著
[code delphi]
function VfyPwd(aAddr: Integer; aPass: Byte): Integer; Stdcall; External 'APIE.dll';
[/code]

[code delphi]
function VfyPwd(aAddr: Integer; aPass: Array of Byte): Integer; Stdcall; External 'APIE.dll';
[/code]
也試過PByte.....等,回傳的值一律是-1, 目前狀況大概就是這樣,

謝謝


編輯記錄
ed_lin 重新編輯於 2011-11-05 06:06:41, 註解 無‧
ed_lin 重新編輯於 2011-11-05 06:08:53, 註解 無‧
Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#6 引用回覆 回覆 發表時間:2011-11-05 20:46:38 IP:122.126.xxx.xxx 訂閱
unsigned char* 是字元指標..所以 Delphi 內可用 PAnsiChar..

初步看到 API 原型 -> int WINAPI VfyPwd(int nAddr,unsigned char* pPassword);
(PS. 挺好奇 nAddr 為何是設成常數 nDevAddr 0xffffffff )
假設參數1 nAddr 與參數2 pPassword 真的一定要給 nDevAddr 和 '0000' 的話, Delphi 可以宣告成這樣

[code delphi]
function VfyPwd(aAddr: Integer; aPass: PAnsiChar): Integer; Stdcall; External 'APIE.dll';
[/code]

然後調用時

[code delphi]
var
iAddr, iReturnValue : Integer;
sPassword : AnsiString;
begin
iAddr := nDevAddr;
sPassword := '0000';
iReturnValue := VfyPwd(iAddr, PAnsiChar(sPassword));
end;
[/code]
ed_lin
一般會員


發表:1
回覆:8
積分:1
註冊:2011-11-03

發送簡訊給我
#7 引用回覆 回覆 發表時間:2011-11-06 19:40:37 IP:1.200.xxx.xxx 訂閱
Dear Victor4022:

謝謝您的回答, 試過你說的方法,
另外我也陸續試了底下幾種方式,依然無解, 讓您參考一下


[code delphi]
function VfyPwd(nAddr : integer; pPassword: PAnsiChar): Integer; stdcall; external 'APIE.dll'; overload;
function VfyPwd(nAddr : integer; pPassword: Byte): Integer; stdcall; external 'APIE.dll'; overload;
function VfyPwd(nAddr : integer; pPassword: Array of Byte): Integer; stdcall; external 'APIE.dll'; overload;
function VfyPwd(nAddr : integer; pPassword: PChar): Integer; stdcall; external 'APIE.dll'; overload;
function VfyPwd(nAddr : integer; pPassword: Array of Char): Integer; stdcall; external 'APIE.dll'; overload;
function VfyPwd(nAddr : integer; pPassword: PPByte): Integer; stdcall; external 'APIE.dll'; overload;
function VfyPwd(nAddr : integer; pPassword: PByte): Integer; stdcall; external 'APIE.dll'; overload;
function VfyPwd(nAddr : integer; pPassword: Variant): Integer; stdcall; external 'APIE.dll'; overload;
[/code]
Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#8 引用回覆 回覆 發表時間:2011-11-06 20:57:25 IP:122.126.xxx.xxx 訂閱
您好,看問題至此,建議您可以問廠商參數一、參數二內含為何,
看到 API 原型 -> int WINAPI VfyPwd(int nAddr,unsigned char* pPassword);
第二個參數 unsigned char* pPassword 在 Delphi 的確可以用 pPassword :PAnsiChar 這樣宣告沒錯,
挺好奇第一個參數: nAddr 為何是設成常數 nDevAddr 0xffffffff ?

既然廠商不熟 Delphi,建議可將 c 碼 smaple code 放上來看看,
或是請廠商在 Dll 的 VfyPwd 進入時 將caller 的傳入參數使用 OutputDebugString 輸出。




ed_lin
一般會員


發表:1
回覆:8
積分:1
註冊:2011-11-03

發送簡訊給我
#9 引用回覆 回覆 發表時間:2011-11-06 21:28:25 IP:1.200.xxx.xxx 訂閱
Dear Victor4022:

謝謝您的提議, 不過稍微有點小困難,
簡單的說那個 Dll(或lib) 是國外硬體商提供給台灣廠商的,
台灣的廠商則是寫VC 6.0去呼叫Dll驅動硬體,
因為我們跟台灣廠商購買硬體,所以他有附VC 6.0 的DEMO程式碼給我們,
難題就是我們公司都是以Delphi為主,根本就沒人會VC ,
現在就是摸著頭寫寫看,目前還想不出其他更好的做法,

謝謝您這幾次的回答



編輯記錄
ed_lin 重新編輯於 2011-11-06 06:31:57, 註解 無‧
ed_lin
一般會員


發表:1
回覆:8
積分:1
註冊:2011-11-03

發送簡訊給我
#10 引用回覆 回覆 發表時間:2011-11-07 12:44:13 IP:59.124.xxx.xxx 訂閱
早上廠商回覆著這一行 b[0]:=0;
試著套進去程式碼, 居然OK了, 不過為何要這樣還是一頭霧水,莫非要傳入的內容只是一個0!



function VfyPwd(nDevAddr: Integer; pPassword: Array of Byte): Integer; stdcall; external 'APIE.dll';
procedure TForm1.BitBtn11Click(Sender: TObject);
const
nDevAddr = -1;
var
iReturnValue: Integer;
b: Array[0..3] of Byte;
begin
ListBox1.Clear;
b[0]:=0;
iReturnValue:=VfyPwd(nDevAddr, b);
ListBox1.Items.Add('VfyPwd: ' IntToStr(iReturnValue));
end;

編輯記錄
ed_lin 重新編輯於 2011-11-06 21:45:09, 註解 無‧
ed_lin 重新編輯於 2011-11-06 21:45:46, 註解 無‧
Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#11 引用回覆 回覆 發表時間:2011-11-07 20:49:54 IP:114.34.xxx.xxx 訂閱
喔不,是我講笑話了!!
unsigned char iPwd[4] {0}
是 4 個 #0 的 char, 小弟幫您出主意宣告成 '0000' String --> '0' 的 ASCII code 為#48,而貴廠商要求的是 #0
所以您傳入四個 #0 的 BYTE array 會正常就是這個原因:(

抱歉看笑話了:(
ed_lin
一般會員


發表:1
回覆:8
積分:1
註冊:2011-11-03

發送簡訊給我
#12 引用回覆 回覆 發表時間:2011-11-07 21:11:29 IP:1.200.xxx.xxx 訂閱
還是謝謝您, 至少多學了一樣~

剛剛忘了說, 是只傳一個0而已,

var ary: Array[0..3] of Byte
ary[0]:=0;

其餘不給值, 因為這樣, 有點納悶~

編輯記錄
ed_lin 重新編輯於 2011-11-07 06:16:16, 註解 無‧
ed_lin
一般會員


發表:1
回覆:8
積分:1
註冊:2011-11-03

發送簡訊給我
#13 引用回覆 回覆 發表時間:2011-11-07 23:49:22 IP:1.200.xxx.xxx 訂閱
抱歉, 延續之前的內容, 剛剛又遇到了一個問題,

unsigned char gpImageData[256*288] 是VC 的變數然後是接一個BMP(圖檔)的資料

那麼我在Delphi 呼叫Dll時用 var aryImage: Array[0..73727] of Byte 去接正確嗎?

還是要用其他型態去接呢?

如果用Array of Byte 是可行的話, 那麼我要透過什樣的方式轉回BMP呢?

謝謝, 如果有需要另外開主題的話請告知, 我再另外開一個主題, 謝謝~

Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#14 引用回覆 回覆 發表時間:2011-11-08 07:47:44 IP:122.126.xxx.xxx 訂閱
我想到一招是透過 DLL 接回來的 BMP binary 格式,利用 TMemoryStream 存成檔案:

[code delphi]
var
ms : TMemoryStream;
begin
ms := TMemoryStream.Create;
ms.SetSize(256 * 288);
ZeroMemory(ms.Memory, ms.Size);
// 透過 DLL 取回 bmp
GetBMPBinaryFromDLL(ms.Memory); // 視 DLL export function 內容給參數
ms.SaveToFile('x:\my.bmp');
end;
[/code]

不管是透過 TMemoryStream 或是 Array of Byte
除非您要透過程式去使用這些 BMP 的 binary 資料
否則應該是存成檔案進行瀏覽, 對吧?
希望對您有幫助 :D



===================引 用 ed_lin 文 章===================
抱歉, 延續之前的內容, 剛剛又遇到了一個問題,

unsigned char gpImageData[256*288] 是VC 的變數然後是接一個BMP(圖檔)的資料

那麼我在Delphi 呼叫Dll時用 var aryImage: Array[0..73727] of Byte 去接正確嗎?

還是要用其他型態去接呢?

如果用Array of Byte 是可行的話, 那麼我要透過什樣的方式轉回BMP呢?

謝謝, 如果有需要另外開主題的話請告知, 我再另外開一個主題, 謝謝~

ed_lin
一般會員


發表:1
回覆:8
積分:1
註冊:2011-11-03

發送簡訊給我
#15 引用回覆 回覆 發表時間:2011-11-08 18:08:27 IP:59.124.xxx.xxx 訂閱
Dear Victor4022:

再次謝謝您的回覆, 有試過照您的方式執行,

不過似乎Dll回傳的內容沒辦法用 TMemoryStream 去接,

倒是用Array of Byte 的方式可以, 想再請教, 您做過 Array of Byte convert BMP 嗎?

問了谷歌神倒是一推 BMP to Array of Byte,

Thanks!



===================引 用 Victor4022 文 章===================
我想到一招是透過 DLL 接回來的 BMP binary 格式,利用 TMemoryStream 存成檔案:

[code delphi]
var
ms : TMemoryStream;
begin
ms := TMemoryStream.Create;
ms.SetSize(256 * 288);
ZeroMemory(ms.Memory, ms.Size);
// 透過 DLL 取回 bmp
GetBMPBinaryFromDLL(ms.Memory); // 視 DLL export function 內容給參數
ms.SaveToFile('x:\my.bmp');
end;
[/code]

不管是透過 TMemoryStream 或是 Array of Byte
除非您要透過程式去使用這些 BMP 的 binary 資料
否則應該是存成檔案進行瀏覽, 對吧?
希望對您有幫助 :D




Victor4022
中階會員


發表:0
回覆:76
積分:90
註冊:2011-02-20

發送簡訊給我
#16 引用回覆 回覆 發表時間:2011-11-09 22:51:59 IP:122.126.xxx.xxx 訂閱
 目前工作的需求還沒用到 bmp 的部份...小弟幫不上忙了 :D

===================引 用 ed_lin 文 章===================
Dear Victor4022:

再次謝謝您的回覆, 有試過照您的方式執行,

不過似乎Dll回傳的內容沒辦法用TMemoryStream 去接,

倒是用Array of Byte 的方式可以, 想再請教, 您做過Array of Byte convert BMP嗎?

問了谷歌神倒是一推BMP toArray of Byte,

Thanks!


系統時間:2017-12-11 19:06:26
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!