동적으로 메모리 할당에 관한 님의 말씀을 듣고 코딩을 어떤식으로 해야 할지 몰라서 제가 생각하는 대로 올려봤습니다. 이렇게 하면 될런지 봐주세요.
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.
얼큰입다...
여러개 보다는... 예제 유닛을 넣었습다...
하는 거는 저번의 예제처럼... 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;
그럼 오늘도 즐입다...