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

Delphi呼叫DLL無法傳回字串

答題得分者是:syntax
comewish
一般會員


發表:1
回覆:7
積分:1
註冊:2010-03-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2010-04-21 02:22:35 IP:99.226.xxx.xxx 訂閱
我使用Delphi開發程式,需要呼叫C++寫的DLL

C 的H檔定義節錄如下:

[code cpp]
//取得資訊
WLDTW_DLL_API int WDLL_iGetInfo(const int iInfoType/*_INFO_TYPE*/,
const int iInput,
const char* pszInput,
int* piOutput,
char* pszOutput);
[/code]

我的Delphi宣告如下

[code delphi]
function WDLL_iGetInfo(const iInfoType:integer {_INFO_TYPE};
const iInput: integer;
const Input: PAnsiChar;
var piOutput:Integer;
var pszOutput: PAnsiChar): integer; cdecl; external 'WLDTW_DLL.dll';
[/code]

此DLL有提供C sample使用以下的方式呼叫上面的Function
[code cpp]
char* pszGetSymbolByIdx(int iIdx)
{
//取得商品名
szSymbol[0] = '\0';
WDLL_iGetInfo(IT_SYMBOL_BY_IDX, iIdx, NULL, NULL, szSymbol);
return szSymbol;
}
[/code]

我把上面的sample轉換為Delphi的方式呼叫function但是無法傳回我需要的字串
[code delphi]
function GetSymbolByID( ID : integer) : string ;
var
FSymbolName : PAnsiChar ;
iOutput: integer ;
begin
FSymbolName := chr(0) ;
WDLL_iGetInfo(IT_SYMBOL_BY_IDX, ID ,nil,iOutput, FSymbolName);
result := String(FSymbolName) ;
end ;
[/code]

C 的Sample Code可以正確的傳回字串資料,但是我用Delphi寫的code卻只能傳回數字資料,無法傳回文字資料,不知道是那裏出了問題,還望這裏的高手能指導一下。
boss.tw
高階會員


發表:15
回覆:109
積分:194
註冊:2005-05-17

發送簡訊給我
#2 引用回覆 回覆 發表時間:2010-04-21 13:09:50 IP:218.210.xxx.xxx 訂閱
之前遇到是在 dll function 宣告 __stdcall 解決
comewish
一般會員


發表:1
回覆:7
積分:1
註冊:2010-03-31

發送簡訊給我
#3 引用回覆 回覆 發表時間:2010-04-21 21:26:20 IP:99.226.xxx.xxx 訂閱
謝謝你的回答,我不太理解的是為何它的Sample可以正常運作,是不是我的宣告有問題?或是Delphi只能用stdcall不能用cdecl
comewish
一般會員


發表:1
回覆:7
積分:1
註冊:2010-03-31

發送簡訊給我
#4 引用回覆 回覆 發表時間:2010-04-21 21:38:53 IP:99.226.xxx.xxx 訂閱
事實上stdcall的方式我也試過了,不過結果也是相同

[code delphi]
//取得資訊
function WDLL_iGetInfo(const iInfoType:integer {_INFO_TYPE};
const iInput: integer;
const Input: PChar;
var piOutput:Integer;
var pszOutput: PChar): integer; stdcall; external 'WLDTW_DLL_stdcall.dll' index 3;

[/code]

這個問題已經卡住我的進度一個多月了,一直無法解決
comewish
一般會員


發表:1
回覆:7
積分:1
註冊:2010-03-31

發送簡訊給我
#5 引用回覆 回覆 發表時間:2010-04-21 21:55:39 IP:99.226.xxx.xxx 訂閱


這是WLDTW_DLL 有無stdcall的函數導出的差異
不過我看不太懂就是了
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#6 引用回覆 回覆 發表時間:2010-04-22 16:27:38 IP:59.125.xxx.xxx 訂閱
1. DLL 一定使用 stdcall
2. szSymbol[0] = '\0'; 與 FSymbolName := chr(0) ; 意義不同

szSymbol[0] = '\0'; 表示宣告了 szSymbol ,其 Size = ? 你沒說,並將 [0] 第一位設為 '\0'
FSymbolName := chr(0) ; 也是將第一位設為 '\0',但是這行這樣寫,FSymbolName 的總長度將會只有 1

先 SetLentch 或 New 吧
先宣告
var
str: String
pstr: PChar;
然後設定長度
SetLength(str,100);
轉換為 PChar
pstr = PChar(str);
傳入呼叫使用
WDLL_iGetInfo(....., pstr );
然後直接使用 pstr (注意 回傳後 str 與 pstr 不一定會是相同的東西,應僅使用 pstr)


===================引 用 comewish 文 章===================


這是WLDTW_DLL 有無stdcall的函數導出的差異
不過我看不太懂就是了
comewish
一般會員


發表:1
回覆:7
積分:1
註冊:2010-03-31

發送簡訊給我
#7 引用回覆 回覆 發表時間:2010-04-23 08:17:19 IP:99.226.xxx.xxx 訂閱
S大你好:

我有試過你的寫法,不過結果依然相同,我把dll的source code放上來,希望能幫我看一下要如何寫才行


WLDTW_DLL_API int WDLL_iGetInfo(const int iInfoType/*_INFO_TYPE*/, const int iInput, const char* pszInput, int* piOutput, char* pszOutput)
{
int iRetValue = 0;
switch(iInfoType)
{
case IT_CONNECTION:
if (iInput >= 0 && iInput < ST_END_OF_ALL && piOutput != NULL)
{
*piOutput = g_ServerParam[iInput].iConnectingStatus;
}
break;
case IT_SYMBOL_BY_IDX: //取商品名稱
if (pszOutput != NULL)
{
strcpy(pszOutput, pszGetSymbolStrByIdx(iInput));
}
break;
case IT_IDX_BY_SYMBOL: //取商品代碼
if (pszInput != NULL && piOutput != NULL)
{
*piOutput = iGetSymbolIdxByID(pszInput);
}
break;
default:
break;
}
return iRetValue;
}
編輯記錄
comewish 重新編輯於 2010-04-23 08:18:29, 註解 無‧
comewish
一般會員


發表:1
回覆:7
積分:1
註冊:2010-03-31

發送簡訊給我
#8 引用回覆 回覆 發表時間:2010-04-23 20:51:53 IP:99.226.xxx.xxx 訂閱
問題找到了,不是stdcall的問題,原因出在宣告上面,因為pchar是指標,所以dll中pchar的宣告不能加var,這樣會造成傳入的值是pchar本身的address
所以正確的寫法應該是

function WDLL_iGetInfo(const iInfoType:integer {_INFO_TYPE};
const iInput: integer;
const Input: PAnsiChar;
var piOutput:Integer;
pszOutput: PAnsiChar): integer; cdecl; external 'WLDTW_DLL.dll';

呼叫的部份也要改一下

function GetSymbolByID( ID : integer) : string ;
var
FSymbolName : PChar ;
str : string ;
iOutput: integer ;
AAA: array[0..100] of Char;
begin
//SetLength(FSymbolName,100);
StrCopy(AAA, '');
WDLL_iGetInfo(IT_SYMBOL_BY_IDX, ID ,nil,iOutput, AAA);
result := String(AAA) ;
end ;

雖然程式已經可以運作了,只是我不太懂的地方是,為何不能用pchar而要用array of char,還是希望有人能指點一下。
這樣問題就解決了,不過還是謝謝大家的幫忙。




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