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

DLL 回傳浮點數錯誤

答題得分者是:dllee
blk5743
高階會員


發表:34
回覆:371
積分:236
註冊:2003-11-17

發送簡訊給我
#1 引用回覆 回覆 發表時間:2008-11-25 14:25:04 IP:60.251.xxx.xxx 訂閱
請問各位前輩
我在主程式傳入一個整數值至DLL 再將此透過DLL整數值讀回來是相符的(網路上下載的程式)
但如果將浮點數傳入DLL 再將此浮點數傳回則會有錯(自己加上去的)
例如傳出1.23 卻得到18354892
我透過將值寫入檔案的方式 確定浮點數傳到DLL時的值沒錯
請問這是怎麼樣的錯誤
我有利用此程式測試傳結構 陣列 Vector等都不會有問題
單就是傳送浮點數不行 想了很久都想不出原因 煩請各位前輩指導

我的環境是XP SP2 BCB6 update 4

[code cpp]
//SharedDll.def
SEGMENTS SHSEG CLASS 'SHCLASS' SHARED

//SharedDll.h
#ifdef __DLL__
#define DLL_EXPORT extern "C" __declspec(dllexport) __stdcall
#else
#define DLL_EXPORT extern "C" __declspec(dllimport) __stdcall
#endif
struct test
{
int age;
int xy;
char *sb;
};
extern int data;
extern float fdata;
#ifdef __DLL__
DLL_EXPORT void SetData(int x);
DLL_EXPORT int GetData(void);
DLL_EXPORT void SetDataf(float x);
DLL_EXPORT float GetDataf(void);

#endif

//---------------------------------------------------------------------------
//SharedDll.cpp
#pragma option -zRSHSEG
#pragma option -zTSHCLASS
#include
#include "SharedDll.h"
#pragma argsused
int data;
float fdata;
test t={120,10,"asdg"};//必要的,不管你用不用
//---------------------------------------------------------------------------
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved)
{
strcpy(t.sb,"ffff");//不知道?什么?用的也做一做
return 1;
}
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
DLL_EXPORT void SetData(int x)
{
data = x;
}
//---------------------------------------------------------------------------
DLL_EXPORT int GetData(void)
{
return data;
}
//---------------------------------------------------------------------------
DLL_EXPORT void SetDataf(float x)
{
fdata = x;
FILE *fp = fopen("a.txt","wt");
fprintf(fp,"%.2f",fdata);
fclose(fp);
}
//---------------------------------------------------------------------------
DLL_EXPORT float GetDataf(void)
{
fdata = 1.23;
return fdata;
}
//---------------------------------------------------------------------------


//main.cpp
#include
#pragma hdrstop
#include "Unit1.h"
#include "SharedDLL.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
DWORD (__stdcall *SetData)(int);
DWORD (__stdcall *GetData)(void);
DWORD (__stdcall *SetData)(float);
DWORD (__stdcall *GetDataf)(void);
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HINSTANCE dll=NULL;
int i = 0;
dll=LoadLibrary("ShareMem.dll");
if( dll )
{
Edit3->Text = "Find DLL";
(FARPROC &)SetData = GetProcAddress(dll, "SetData");
if( SetData )
{
i = Edit1->Text.ToInt();
SetData(i);
}
(FARPROC &)GetData = GetProcAddress(dll, "GetData");
if( GetData )
{
Edit2->Text = GetData();
}
(FARPROC &)SetDataf = GetProcAddress(dll, "SetDataf");
if( SetData )
{
SetDataf(1.23);
}
(FARPROC &)GetDataf = GetProcAddress(dll, "GetDataf");
if( GetDataf )
{
Edit3->Text = GetDataf();
}
FreeLibrary(dll);
}
}
//---------------------------------------------------------------------------

[/code]
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#2 引用回覆 回覆 發表時間:2008-11-28 09:15:19 IP:220.134.xxx.xxx 訂閱

DWORD (__stdcall *GetDataf)(void);

改成

float (__stdcall *GetDataf)(void);
再試試把,因為在使用的程式內,您是把函式定為 DWORD
自然它會回傳值以 DWORD 去解讀。
------
http://www.ViewMove.com
blk5743
高階會員


發表:34
回覆:371
積分:236
註冊:2003-11-17

發送簡訊給我
#3 引用回覆 回覆 發表時間:2008-12-03 10:21:28 IP:60.248.xxx.xxx 訂閱
dllee你好
經過你的指導之後 已經可以正確使用
我原本以為DWORD 指的是DLL中function的位址 現在看起來是回傳值的型態
另外我想請問的是 這程式是一個可以分享記憶體區塊的測試專案
在我的主程式中 在SetData(i)設中斷點時 可在debug window看出DLL中的data值被修改了
在主程式debug window也可以看到data這一個變數 且值被正確的改變了
但是我直接宣告data = i時unresolved external _data的錯誤訊息
但我在.h檔中已經有宣告extern且debug window也可以看到變數的改變 請問該如何解決
另外 int data; float fdata; 我也有改成了int data = 0; float fdata = 0.0; 似乎沒有什麼幫助
if( SetData )
{
i = Edit1->Text.ToInt();
data = i;
//SetData(i);

}
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2008-12-03 12:30:41 IP:60.248.xxx.xxx 訂閱
你的share的部份寫法有誤。

SharedDll.cpp 裡的
pragma option -zRSHSEG
pragma option -zTSHCLASS
int data;
float fdata;
四個敘述要刪除,然後新增一個cpp檔。

比如說取名為 shareseg.cpp 內容如下:

pragma option -zRSHSEG
pragma option -zTSHCLASS
int data = 0;
float fdata = 0.0;

然後把shareseg.cpp加入專案中
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
blk5743
高階會員


發表:34
回覆:371
積分:236
註冊:2003-11-17

發送簡訊給我
#5 引用回覆 回覆 發表時間:2008-12-04 10:15:18 IP:60.251.xxx.xxx 訂閱
aftcast你好
我試了一下 還是跟之前的結果一樣
我整理一下該用的檔案 請你看是否有錯

dll project part
sharedll.cpp 放入dll中要執行的function
sharedll.h 放入要extern的data
shareseg.cpp 放入要共用的變數且初始化
sharedll.def(是和dll function的cpp同名沒錯吧 還是要跟共用變數的cpp同名 我都有試過了) 內容 SEGMENTS SHSEG CLASS 'SHCLASS' SHARED

AP project part main.cpp 呼叫dll function測試
sharedll.h 要看到共用變數的extern
project 加入shareseg.cpp時 main.cpp可以用共用變數 但可以看到是main.cpp及sharedll.cpp各有一個同名但值不相同的變數
project不加入shareseg.cpp時
main.cpp中使用共用變數名稱時
會得到unresolved external的錯誤訊息(如上一例)
main.cpp中不用共用變數名稱時 在debug window可以看到共用變數為(undifined symbol) 但只要LoadLibrary後就可以看到值在dll的變化

所以我想問的是 他們不是共用記憶體嗎 要怎麼樣才能在main.cpp or sharedll.cpp中改變值 另一個.cpp就可以得到改變後的值 而不需要透過參數列去傳址
編輯記錄
blk5743 重新編輯於 2008-12-04 10:17:50, 註解 無‧
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2008-12-04 17:53:08 IP:60.248.xxx.xxx 訂閱
你好,你的問題一開始的時候可能就想錯方向!

所謂的共享dll的資料是指假如你有一個dll名叫 A.DLL 你有二程式會戴入 A.DLL , 假設那二個程式叫 FOO.EXE 與 BAR.EXE
此外假設 A.DLL 裡有一個變數叫 V ,初值是0 ,V這個變數在RUN的時候會改變值。

於是, 當 FOO 載入A.DLL 後,並設定V值 V = 7;
這時候 BAR也載入 A.DLL,此時BAR看到的 V值還是0;
若BAR再修改V = 11,那FOO這時候看V值的結果還是7。

議題: 如何才能讓 FOO改的值同步讓BAR看到? 這就是 「 DLL 共享變數 」的問題了。此時就是用上面我講的方式來共享。

而你最後說的需求和上面講的竟然不同! 你要的是MAIN.EXE去修改DLL的值,或是DLL的值自己修改後,彼此都可以看到結果?!
這樣的需求只相關於1個EXE與1個DLL的情形,和共享DLL的議題完全不同。

最後這個需求只要你把變數v給 EXPORT出來就可以,就如同把FUNCTION給EXPORT出來一樣。 變數也是可以EXPORT的,用法和函式一模一樣。


[code cpp]
//SharedDll.h
#ifdef __DLL__
#define DLL_EXPORT extern "C" __declspec(dllexport) __stdcall
#else
#define DLL_EXPORT extern "C" __declspec(dllimport) __stdcall
#endif
struct test
{
int age;
int xy;
char *sb;
};
//extern int data; //刪除
//extern float fdata; //刪除
#ifdef __DLL__
DLL_EXPORT int data; //加入
DLL_EXPORT fdata; //加入
DLL_EXPORT void SetData(int x);
DLL_EXPORT int GetData(void);
DLL_EXPORT void SetDataf(float x);
DLL_EXPORT float GetDataf(void);

#endif

[/code]

所以ShareSeg與def檔都不用了!

main裡則加入
……
……
float (__stdcall *GetDataf)(void);
extern int data; //加入
extern float fdata; //加入



------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2008-12-04 17:57:54, 註解 無‧
aftcast 重新編輯於 2008-12-04 18:01:37, 註解 無‧
blk5743
高階會員


發表:34
回覆:371
積分:236
註冊:2003-11-17

發送簡訊給我
#7 引用回覆 回覆 發表時間:2008-12-05 15:01:53 IP:60.251.xxx.xxx 訂閱
看來我的想法是有誤解

不過我的應用是在dll中宣告了一些vector, array等global變數
我希望能在主程式中可以像一般專案一樣 透過extern就可以做存取

我有按照aftcase的指導 將.h檔做了修改
extern int data => DLL_EXPORT int data;(放在#ifdef __DLL__中)
用depends.exe可以看到 _data被export出來


但我在主程式中宣告extern int data後 還是會看到unresolved external的錯誤
不知道又是那裡出現錯誤
aftcast
站務副站長


發表:81
回覆:1485
積分:1763
註冊:2002-11-21

發送簡訊給我
#8 引用回覆 回覆 發表時間:2008-12-05 18:37:36 IP:122.120.xxx.xxx 訂閱
你忘了加lib檔了!    看你上面function都是用runtime load dll 的方式,但你可以加入lib檔,就可使用該extern 變數,這時候叫 loadtime load dll
當然,你也許也可以比照你function的方式getprocaddress的方式,但我沒這樣用過,因為沒有比較方便。
------


蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
編輯記錄
aftcast 重新編輯於 2008-12-05 18:39:03, 註解 無‧
blk5743
高階會員


發表:34
回覆:371
積分:236
註冊:2003-11-17

發送簡訊給我
#9 引用回覆 回覆 發表時間:2008-12-08 10:30:53 IP:60.251.xxx.xxx 訂閱
(1)使用.lib
因為我的.dll要給VC跟BCB使用,但似乎沒看到可以將BCB產生的.lib轉成VC .lib的工具

(2)使用GetProcAddress()方法如下
int *pdata;//用一個int指標去接我的變數
pdata = (int *)GetProcAddress(dll, "_data");//去import我的變數
*pdata = 100;//修改變數值

感謝aftcast的指導,我現在可以透過指標的方式去存去我想看變數
但因為這一篇文章的問題傳回浮點數錯誤的部份,是由dllee解決的
所以很抱歉,我還是要把分數給dllee
不過最後還是感謝aftcast的指導
dllee
站務副站長


發表:321
回覆:2519
積分:1711
註冊:2002-04-15

發送簡訊給我
#10 引用回覆 回覆 發表時間:2008-12-15 16:13:20 IP:220.134.xxx.xxx 訂閱
要寫 for VC 的 lib, 要經過轉換。
用 google 查 VC BCB lib, 您會發現有一堆文章是 BCB 如何用 VC lib/dll 或是
VC 如何用 BCB 的 lib/dll (前者的資料比較多,因為 VC 的 lib/dll 不少) ,
其中有許多是本站的討論

至於分數... 已給了, 不能改, 不然, 應該給 aftcast 大大, 因為他真的很用心在說明,
也建議您下次將問題整理好, 一個問題解決, 在出現另一個問題時, 開另一討論文章,
比較不會有不知給誰分數的困擾


VMASK - ViewMove Automation Software KernelVMIO-Server/SECS/GEMdllee's blogdllee's StatPlus
------
http://www.ViewMove.com
系統時間:2024-04-20 22:28:45
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!