全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1515
推到 Plurk!
推到 Facebook!

DLL的問題

尚未結案
jason_cyl329
高階會員


發表:123
回覆:155
積分:105
註冊:2003-05-26

發送簡訊給我
#1 引用回覆 回覆 發表時間:2003-12-24 19:29:20 IP:61.218.xxx.xxx 未訂閱
請問,我自己撰寫動態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

發送簡訊給我
#2 引用回覆 回覆 發表時間:2003-12-25 11:23:46 IP:210.243.xxx.xxx 未訂閱
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

發送簡訊給我
#3 引用回覆 回覆 發表時間:2003-12-26 13:03:56 IP:61.218.xxx.xxx 未訂閱
感謝野人兄的獻智: 我的問題不是出在這裡,我有把Form給delete,不過謝謝你給我的觀念!! 我把我要傳的參數(DLL內的宣告)由char * 改成 AnsiString 就OK了。 這是為什麼?
ENIX007
高階會員


發表:28
回覆:274
積分:185
註冊:2003-11-27

發送簡訊給我
#4 引用回覆 回覆 發表時間:2003-12-26 13:38:31 IP:210.243.xxx.xxx 未訂閱
jason_cyl329您好: 本野人又來了 能否請您把
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
jason_cyl329
高階會員


發表:123
回覆:155
積分:105
註冊:2003-05-26

發送簡訊給我
#5 引用回覆 回覆 發表時間:2003-12-26 14:54:47 IP:61.218.xxx.xxx 未訂閱
ENIX007兄你好, 以下是我的dll程式部分,TMyDlg是== TForm1,我自己另的名稱,上面有8個按鈕, 我又有新的發現,如果我用AnsiString去宣告我的dll中的char *的部分, 傳回值會不對,但是不會出現我說的系統錯誤,但是如果用char *來宣告, 傳三組參數還可以,四組以上就會出現系統錯誤,但是傳回值是正確的!!    
#include 
#pragma hdrstop    #include "Dlg.h"
#include "DlgFrm.h"
//---------------------------------------------------------------------------    #pragma package(smart_init)    int *mrRet;    int __stdcall MyMsgDlg( char* caption,char* DefTxt,char *ButtonType,char *ButtonTxt)//,char* DlgType)
{     int i,j;     MyDlg = new TMyDlg(NULL);//隨便一個Form     MyDlg->ShowModal();     int mrRet = MyDlg->RetFlag;     delete MyDlg;     MyDlg = NULL;     return mrRet;
}    .H
extern "C"{    __declspec (dllexport) int __stdcall MyMsgDlg
  ( char* caption,char* DefTxt,char *ButtonType,char *ButtonTxt);//,char* DlgType);
}
發表人 - taishyang 於 2003/12/26 15:08:33
ENIX007
高階會員


發表:28
回覆:274
積分:185
註冊:2003-11-27

發送簡訊給我
#6 引用回覆 回覆 發表時間:2003-12-26 16:29:54 IP:210.243.xxx.xxx 未訂閱
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::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() );
也就是說使用AnsiString指標操作字串時,該指標必須有自己的位址跟空間... 另外,傳三個參數沒問題,傳四個會有問題,會不會是哪邊函式宣告出問題呢? 個人認為dll程式蠻不好trace的,因為沒辦法trace到dll裡面!! 會出現Access Violation通常都是指標指到不該指的地方或超出範圍...請往 這方面檢查看看... 以上是個人一點小小的心得,不知幫得上忙否? 有任何錯誤也請指教 程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
------
程式迷人之處,在於邏輯思考,然而卻也是惱人之處~~
jason_cyl329
高階會員


發表:123
回覆:155
積分:105
註冊:2003-05-26

發送簡訊給我
#7 引用回覆 回覆 發表時間:2003-12-26 16:50:48 IP:61.218.xxx.xxx 未訂閱
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

發送簡訊給我
#8 引用回覆 回覆 發表時間:2003-12-26 17:28:14 IP:210.243.xxx.xxx 未訂閱
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

發送簡訊給我
#9 引用回覆 回覆 發表時間:2003-12-26 17:59:54 IP:61.218.xxx.xxx 未訂閱
ENIX007你好, 不要這麼說,您太客氣了!! 我已經將程式上傳,你可以先執行看看程式,看看結果,然後再用你的程式來呼叫或是修改,先寄上char *宣告的,然後我再寄上AnsiString宣告的, 傳回值會不是你要的!!
jason_cyl329
高階會員


發表:123
回覆:155
積分:105
註冊:2003-05-26

發送簡訊給我
#10 引用回覆 回覆 發表時間:2003-12-26 18:24:44 IP:61.218.xxx.xxx 未訂閱
感謝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);來令,就會產生問題!!
系統時間:2024-06-27 0:55:56
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!