Q&A

  • 고지범님 봐주세요. 동적메모리 할당 추가 질문입니다.
동적으로 메모리 할당에 관한 님의 말씀을 듣고 코딩을 어떤식으로 해야 할지 몰라서 제가 생각하는 대로 올려봤습니다. 이렇게 하면 될런지 봐주세요.

unit common;

Interface
   uses ........

   type
      TFunc1 = Function(str:string):boolean;stdcall;
      TFunc2 = Function(i:integer):boolean;stdcall;
                    TFunc10 까지 존재.
   var
       Func1 : TFunc1;
       Func2 : TFunc2;
          Func10까지 존재.

       H1,H2.H3.H4,H5.......H10:THandle;

   procedure createhandle; //dll의 메모리번지를 가져오기
  
implementation

procedure createhandle;
begin
        H1 := LoadLibrary('A1.Dll');
        H2 := LoadLibrary('A2.Dll');
                  H10까지 로드하구
        @Func1 := GetProcAddress(H1,'operation1');
        @Func2 := GetProcAddress(H2.'operation2');
              이렇게 10개의 함수의 메모리 번지를 가져와서 다른
               유닛에서 상용하면 될까요?
end;
end.
        

1  COMMENTS
  • Profile
    고지범 2002.09.03 21:11
    에궁... 여러 고수님들도 많으신디 넘 쑥스러브....
    얼큰입다...
    여러개 보다는... 예제 유닛을 넣었습다...
    하는 거는 저번의 예제처럼... ComCtl32.dll에 있는 DllGetVersion을 매핑하는 겁니다. (게으르다구 구박하지 마시길... 퍼억, 허걱...)
    참고로 아래의 유닛은 델파이 6 기준입니다. 아마 function pointer 에 관한 거는 델파이 5랑 별 차이 없기에 암데나 돌겁니다... (언제 델파이 6로 바꾸었다구 그세 까먹었습다...ㅜㅜ)

    unit common;

    interface
    uses
       // Windows unit에서 필요한게 다 있으므로 이것만 있으면 됩니다...
       Windows;
    type
       // DllGetVersion에서 필요한 Data Structure, 포인터 형도 언제나..같이 선언.^^
       DLLVERSIONINFO = record
          cbSize         :DWORD;
          dwMajorVersion :DWORD;
          dwMinorVersion :DWORD;
          dwBuildNumber  :DWORD;
          dwPlatformID   :DWORD;
       end;
       PDLLVERSIONINFO = ^DLLVERSIONINFO;

       // 요고이 필요한 function pointer
       TDllGetVersion = function (a_PassedPointer:PDLLVERSIONINFO):HRESULT;stdcall;
    var
       // 이 유닛 밖에서 보믄 요놈 밖에 안 보임... ^^
       DllGetVersion  :TDllGetVersion;

    implementation
    var
       // DllGetVersion 함수를 담고 있을 DLL-handle 변수.
       Handle_Of_DllGetVersion :THandle;
       // GetProcAddress가 오동작할 수도 있으니 일단 임시 변수로...
       tempPointer :Pointer;

    // 만일 필요한 함수가 없을 시에 대체할 에러 함수.
    function ErroredDllGetVersion(a_PassedPointer:PDLLVERSIONINFO):HRESULT;stdcall;
    begin
       MessageBox(0,PChar('DllGetVersion 함수 없습다.'),PChar('Error'),MB_OK);
       Result := ERROR_INVALID_FUNCTION;
    end;

    // initialization 부분은 언!제!나! 불립니다... 순서의 차이가 있으나...
    // 암튼, Application.Initialize 보다는 먼저 불립니다. 어떤 유닛의 initializtion이
    // 먼저 불릴지는 몰지만...
    initialization
       // 표준 코딩 이죠?
       Handle_Of_DllGetVersion := LoadLibrary(PChar('comctl32.dll'));

       // 일단 에러 관련 함수로 넣어 놓고... 요거이 관건이죠...
       DllGetVersion := ErroredDllGetVersion;

       if (INVALID_HANDLE_VALUE <> Handle_Of_DllGetVersion) and
          (0 <> Handle_Of_DllGetVersion) then begin
          tempPointer := GetProcAddress(Handle_Of_DllGetVersion,
                                        PChar('DllGetVersion'));
          // 만일 해당 함수가 있으면 필요한 함수로 치환...
          if nil <> tempPointer then DllGetVersion := tempPointer;
       end;

    // 프로세스가 죽는 경우에는 LoadLibrary로 올라간 녀석들이 모두 내려오지만...
    // 그래도 명시적인거이 좋겠죠?
    // 암튼 finalization 부분은 메인 폼이 죽구 난 다음 언!제!나! 불립니다.
    // initialization 과 마찬가지로 순서는... 잘....쩌비...
    finalization
       // 역시 표준 코딩이죠?
       if (INVALID_HANDLE_VALUE <> Handle_Of_DllGetVersion) and
          (0 <> Handle_Of_DllGetVersion) then
          FreeLibrary(Handle_Of_DllGetVersion);
    end.


    밖에서 쓰는 거는 아시죠? 걍 호출하는 거...
    procedure TForm1.Button1Click(Sender: TObject);
    var
       temp  :DLLVERSIONINFO;
    begin
       temp.cbSize := SizeOf(temp);
       if ERROR_SUCCESS = DllGetVersion(@temp) then
          with temp do
             ShowMessage('cbSize         : ' + IntToStr(cbSize) + #13#10 +
                         'dwMajorVersion : ' + IntToStr(dwMajorVersion) + #13#10 +
                         'dwMinorVersion : ' + IntToStr(dwMinorVersion) + #13#10 +
                         'dwBuildNumber  : ' + IntToStr(dwBuildNumber) + #13#10 +
                         'dwPlatformID   : ' + IntToStr(dwPlatformID) );
    end;

    그럼 오늘도 즐입다...