DLL的問題 |
尚未結案
|
jason_cyl329
高階會員 發表:123 回覆:155 積分:105 註冊:2003-05-26 發送簡訊給我 |
請問,我自己撰寫動態Dll有執行所需的動作,可是執行到FreeLibrary(hInst);
卻會出現以下貼圖的錯誤,為什麼? hInst = LoadLibrary("PrjMsg.DLL"); (FARPROC &)MyMsgDlg = GetProcAddress(hInst,"MyMsgDlg"); //ShowImage();
MyMsgDlg("確認","What are you doing",1,"YESNO","確認_不要",NULL);
FreeLibrary(hInst);
|
ENIX007
高階會員 發表:28 回覆:274 積分:185 註冊:2003-11-27 發送簡訊給我 |
jason_cyl329您好:
小弟又來野人獻曝了
經小弟測試結果,問題出在於>資源>
測試經過如下:
先寫一個最簡單的 class="code">
void __stdcall Create()
{
ShowMessage("OK");
}
開新專案,放一個button,呼叫DLL:
void (__stdcall *F_Create)(); void __fastcall TForm1::Button1Click(TObject *Sender) { HANDLE handle; handle = LoadLibrary("ShowMessage.dll"); (FARPROC &)F_Create = GetProcAddress(handle,"Create"); F_Create(); FreeLibrary(handle); }這樣是沒問題的... 接著是含有Form的DLL: USEFORM("Form1.cpp", Form); //--------------------------------------------------------------------------- void __stdcall Create() { Form = new TForm(NULL); Form->Show(); } //--------------------------------------------------------------------------- void __stdcall Destroy() { if ( Form != NULL ) { delete Form; Form = NULL; } }呼叫該dll: void (__stdcall *F_Create)(); void (__stdcall *F_Destroy)(); void __fastcall TForm1::Button1Click(TObject *Sender) { HANDLE handle; handle = LoadLibrary("Form.dll"); (FARPROC &)F_Create = GetProcAddress(handle,"Create"); (FARPROC &)F_Destroy = GetProcAddress(handle,"Destroy"); F_Create(); F_Destroy(); //沒有這行就掛了 FreeLibrary(handle); }以上測試心得就是要將dll的handle釋放前,必須先釋放dll內用到的資源(如上述Form) 以上測試如有錯誤請指正 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ |
jason_cyl329
高階會員 發表:123 回覆:155 積分:105 註冊:2003-05-26 發送簡訊給我 |
|
ENIX007
高階會員 發表:28 回覆:274 積分:185 註冊:2003-11-27 發送簡訊給我 |
|
jason_cyl329
高階會員 發表:123 回覆:155 積分:105 註冊:2003-05-26 發送簡訊給我 |
ENIX007兄你好,
以下是我的dll程式部分,TMyDlg是== TForm1,我自己另的名稱,上面有8個按鈕,
我又有新的發現,如果我用AnsiString去宣告我的dll中的char *的部分,
傳回值會不對,但是不會出現我說的系統錯誤,但是如果用char *來宣告,
傳三組參數還可以,四組以上就會出現系統錯誤,但是傳回值是正確的!!
#include發表人 - taishyang 於 2003/12/26 15:08:33 |
ENIX007
高階會員 發表:28 回覆:274 積分:185 註冊:2003-11-27 發送簡訊給我 |
jason_cyl329您好
問題似乎越來越複雜了
首先,小弟測試的結果,如果只是單純差在函數型態為 class="code">
TForm1 *Form1;
typedef void ( __stdcall *FORM_FUNC)(AnsiString);
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
HINSTANCE hInst = NULL; hInst = LoadLibrary( "StatusForm.dll" );
if ( hInst == NULL )
return; (FARPROC &) F_Create = GetProcAddress( hInst,"Create");
(FARPROC &) F_Destroy = GetProcAddress( hInst,"Destroy");
(FARPROC &) F_Add = GetProcAddress( hInst,"Add");
(FARPROC &) F_App = GetProcAddress( hInst,"App"); F_Create();
}
//--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender)
{
F_Add("test");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
F_App("test");
}
//---------------------------------------------------------------------------
dll部分:(本身就是一個Form-->F_Status)
USEFORM("Form_Status.cpp", F_Status); //--------------------------------------------------------------------------- extern "C" __declspec(dllexport) void __stdcall Create(); extern "C" __declspec(dllexport) void __stdcall Destroy(); extern "C" __declspec(dllexport) void __stdcall Add( AnsiString Msg); extern "C" __declspec(dllexport) void __stdcall App( AnsiString Msg); //--------------------------------------------------------------------------- int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) { return 1; } //--------------------------------------------------------------------------- void __stdcall Create() { F_Status = new TF_Status(NULL); F_Status->Show(); } //--------------------------------------------------------------------------- void __stdcall Destroy() { if ( F_Status != NULL ) { delete F_Status; F_Status = NULL; } } //--------------------------------------------------------------------------- void __stdcall Add( AnsiString Msg ) { F_Status->RichEdit1->Lines->Add( Msg ); } //--------------------------------------------------------------------------- void __stdcall App( AnsiString Msg ) { int Count; String Src; Count = F_Status->RichEdit1->Lines->Count - 1; Src = F_Status->RichEdit1->Lines->Strings[Count]; F_Status->RichEdit1->Lines->Strings[Count] = Src Msg; } //---------------------------------------------------------------------------當按下button1時,F_Status的RichEdit會出現test,按下button2時 會在其後加上一個test,請注意 使用char*或AnsiString都是可以的 因此我想有一種可能,也是我曾經遇過的 使用AnsiString.cstr()時注意事項,以下是BCB Online Help的說明 引言:也就是說使用AnsiString指標操作字串時,該指標必須有自己的位址跟空間... 另外,傳三個參數沒問題,傳四個會有問題,會不會是哪邊函式宣告出問題呢? 個人認為dll程式蠻不好trace的,因為沒辦法trace到dll裡面!! 會出現Access Violation通常都是指標指到不該指的地方或超出範圍...請往 這方面檢查看看... 以上是個人一點小小的心得,不知幫得上忙否? 有任何錯誤也請指教 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~AnsiString::c_str() returns a non const temporary pointer to the internal string buffer in the AnsiString object. The pointer is invalid once the statement in which it is used has finished executing. That is,don't do something like this: char* cp = Edit1->Text.c_str(); char* cp2 = strtok( cp, " \t\n" ); // cp may no longer be valid If you need a persistent pointer, you MUST copy the string into its own buffer: char* cp = new char[ Edit1->Text.Length() 1 ]; strcpy( cp, Edit1->Text.c_str() );
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ |
jason_cyl329
高階會員 發表:123 回覆:155 積分:105 註冊:2003-05-26 發送簡訊給我 |
ENIX007 你好,
用你的宣告方式不會有問題,因為只有一個參數,
我覺得,你可以照我的宣告來做呼叫,如下,
int __stdcall MyMsgDlg( char* caption,char* DefTxt,char *ButtonType,char *ButtonTxt)
只要有這個格式來呼叫即可,有沒有new Form沒有關係,
或是將char *改成AnsiString 注意有個傳回值,
隨便return 1;
然後再呼叫的地方
Ex. Ret = MyMsgDlg("AAA","BBB","CCC","DDD");
監控Ret的值是否為1,我這裡測試的結果為AnsiString宣告,回傳值為1243....
很大的值,char *宣告回傳值為1,我使用單步trace,可以進入dll的程式也,
還有一個問題,我新立一個好了,這樣如果有解決,就可得兩提的分數!!
|
ENIX007
高階會員 發表:28 回覆:274 積分:185 註冊:2003-11-27 發送簡訊給我 |
jason_cyl329您好:
報告測試結果...還是ok耶
針對您懷疑的部分,作了以下測試:
class="code">
extern "C" __declspec(dllexport) int __stdcall MyMsgDlg( char* caption,char* DefTxt,char *ButtonType,char *ButtonTxt);
extern "C" __declspec(dllexport) int __stdcall MyMsgDlgAnsi( AnsiString caption,AnsiString DefTxt,AnsiString ButtonType,AnsiString ButtonTxt);
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
return 1;
}
//---------------------------------------------------------------------------
int __stdcall MyMsgDlg( char* caption,char* DefTxt,char *ButtonType,char *ButtonTxt)
{
ShowMessage(caption);
ShowMessage(DefTxt);
ShowMessage(ButtonType);
ShowMessage(ButtonTxt);
return 1;
}
//---------------------------------------------------------------------------
int __stdcall MyMsgDlgAnsi( AnsiString caption,AnsiString DefTxt,AnsiString ButtonType,AnsiString ButtonTxt)
{
ShowMessage(caption);
ShowMessage(DefTxt);
ShowMessage(ButtonType);
ShowMessage(ButtonTxt);
return 2;
}
呼叫部分:
.h檔 typedef int ( __stdcall *FORM_FUNC)(char* caption,char* DefTxt,char *ButtonType,char *ButtonTxt); typedef int ( __stdcall *FORM_FUNC1)(AnsiString caption,AnsiString DefTxt,AnsiString ButtonType,AnsiString ButtonTxt); class TForm1 : public TForm { __published: // IDE-managed Components TButton *Button1; TLabel *Label1; TButton *Button2; void __fastcall Button1Click(TObject *Sender); void __fastcall Button2Click(TObject *Sender); private: // User declarations public: // User declarations __fastcall TForm1(TComponent* Owner); FORM_FUNC MyMsgDlg; FORM_FUNC1 MyMsgDlgAnsi; }; //--------------------------------------------------------------------------- extern PACKAGE TForm1 *Form1; //--------------------------------------------------------------------------- .cpp檔 TForm1 *Form1; //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { HINSTANCE hInst = NULL; hInst = LoadLibrary( "Project1.dll" ); if ( hInst == NULL ) return; (FARPROC &) MyMsgDlg = GetProcAddress( hInst,"MyMsgDlg"); (FARPROC &) MyMsgDlgAnsi= GetProcAddress( hInst,"MyMsgDlgAnsi"); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { int Ret; Ret = MyMsgDlg("AAA","BBB","CCC","DDD"); Label1->Caption = IntToStr(Ret); } //--------------------------------------------------------------------------- void __fastcall TForm1::Button2Click(TObject *Sender) { int Ret; Ret = MyMsgDlgAnsi("AAA","BBB","CCC","DDD"); Label1->Caption = IntToStr(Ret); } //---------------------------------------------------------------------------測試結果, 當按下button1,跳出4個MessageBox,顯示"AAA","BBB","CCC","DDD" 然後Label顯示1<--char* 當按下button2,跳出4個MessageBox,顯示"AAA","BBB","CCC","DDD" 然後Label顯示2<--AnsiString 所以應該不是這個問題 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~ |
jason_cyl329
高階會員 發表:123 回覆:155 積分:105 註冊:2003-05-26 發送簡訊給我 |
|
jason_cyl329
高階會員 發表:123 回覆:155 積分:105 註冊:2003-05-26 發送簡訊給我 |
感謝ENIX007,
我想我找到原因了,原因是以下的宣告:
typedef int (__stdcall *MYMSGDLG)(AnsiString caption,AnsiString DefTxt,AnsiString ButtonType,AnsiString ButtonTxt);
MYMSGDLG MyMsgDlg; 我是直接用
int (*MyMsgDlg)(char* caption,char* DefTxt,char *ButtonType,char *ButtonTxt);來令,就會產生問題!!
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |