안녕하세요..델파이는 아직 높은산으로 느끼는 사람입니다.
다름이 아니라 C++로 짠 DLL을 델파이에서 호출을 하려고 하는데요...
으으...아직 델파이 개념이 별로 없어서...힘드네요.
적절히 끼워맞춰보고 호출을 했는데 여지없이 violation error가 뜹니다.
'Access violation at address 00000003. Read of address FFFFFFFF'
일케 뜨는군요.
정말 급한데...어케해야하죠?
도움 좀 부탁드리겠습니다.
1. C측의 헤더.
struct sChannelHandle {
ULONG dwHwnd;
ULONG dwMsg;
ULONG dwBaseAddress;
ULONG dwIOPort;
ULONG dwChannel;
unsigned char *pBuffer;
BYTE cCodecType;
BYTE cPCMType;
short wNum;
unsigned char *pFilename;
short wMaxWrite;
HANDLE hContentDevice;
HANDLE hProtelDevice;
HANDLE pSemaphore;
short wUserChannel;
};
typedef struct sChannelHandle ChannelHandle;
2. DLL 루틴.
ChannelHandle* PtOpenChannelHandle( int wChannelNumber, HWND Hwnd, UINT Msg,short Mask );
인자
int wChannelNumber
원하는 채널 번호 값
1~64사이만 가능
HWND Hwnd
메시지를 받고자 하는 윈도우의 핸들값
UINT Msg
받고자 하는 메시지의 ID
short Mask
1 : 반드시 Close된 채널만 사용할수 있다
2 : Close 되지 않은 채널도 Open할 수 있다
Return 값
성공 : ChannelHandle *
실패 : FALSE
3. 호출예제(델파이)
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
{ 버튼이 눌리면 DLL 함수 실행 }
end;
sChannelHandle = packed record
dwHwnd : LongWord;
dwMsg : LongWord;
dwBaseAddress : LongWord;
dwIOPort : LongWord;
dwChannel : LongWord;
pBuffer : PChar;
cCodecType : Byte;
cPCMType : Byte;
wNum : Integer;
pFilename : PChar;
wMaxWrite : Integer;
hContentDevice : LongWord;
hProtelDevice : LongWord;
pSemaphore : LongWord;
wUserChannel : Integer;
end;
pChannelHandle = ^sChannelHandle;
const
WM_PROTEL : LongWord = 100;
{ THandle = integer;
TCharLower = procedure(str1 : PChar);
}
var
Form1: TForm1;
ChannelHandle : pChannelHandle;
{ Handle : THandle;
CharLower : TCharLower;
}
implementation
{$R *.DFM}
function PtOpenChannelHandle(wChannelNumber:Integer; pHwnd:hwnd; Msg:word; Mask:Integer) : pChannelHandle; stdcall; external 'abc.dll';
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.caption := '123';
{ Label1.caption := CharLowerA('Abc Def ghi');}
ChannelHandle := PtOpenChannelHandle(1, Application.handle, WM_PROTEL, 1);
end;
begin
end.
> 안녕하세요..델파이는 아직 높은산으로 느끼는 사람입니다.
> 다름이 아니라 C++로 짠 DLL을 델파이에서 호출을 하려고 하는데요...
> 으으...아직 델파이 개념이 별로 없어서...힘드네요.
>
> 적절히 끼워맞춰보고 호출을 했는데 여지없이 violation error가 뜹니다.
> 'Access violation at address 00000003. Read of address FFFFFFFF'
> 일케 뜨는군요.
> 정말 급한데...어케해야하죠?
> 도움 좀 부탁드리겠습니다.
>
>
> 1. C측의 헤더.
> struct sChannelHandle {
> ULONG dwHwnd;
> ULONG dwMsg;
> ULONG dwBaseAddress;
> ULONG dwIOPort;
> ULONG dwChannel;
> unsigned char *pBuffer;
> BYTE cCodecType;
> BYTE cPCMType;
> short wNum;
> unsigned char *pFilename;
> short wMaxWrite;
> HANDLE hContentDevice;
> HANDLE hProtelDevice;
> HANDLE pSemaphore;
> short wUserChannel;
> };
>
> typedef struct sChannelHandle ChannelHandle;
>
> 2. DLL 루틴.
> ChannelHandle* PtOpenChannelHandle( int wChannelNumber, HWND Hwnd, UINT Msg,short Mask );
>
> 인자
> int wChannelNumber
> 원하는 채널 번호 값
> 1~64사이만 가능
>
> HWND Hwnd
> 메시지를 받고자 하는 윈도우의 핸들값
>
> UINT Msg
> 받고자 하는 메시지의 ID
>
> short Mask
> 1 : 반드시 Close된 채널만 사용할수 있다
> 2 : Close 되지 않은 채널도 Open할 수 있다
>
> Return 값
> 성공 : ChannelHandle *
> 실패 : FALSE
>
> 3. 호출예제(델파이)
> unit Unit1;
>
> interface
>
> uses
> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
> StdCtrls;
>
> type
> TForm1 = class(TForm)
> Button1: TButton;
> Label1: TLabel;
> procedure Button1Click(Sender: TObject);
> { 버튼이 눌리면 DLL 함수 실행 }
> end;
>
> sChannelHandle = packed record
> dwHwnd : LongWord;
> dwMsg : LongWord;
> dwBaseAddress : LongWord;
> dwIOPort : LongWord;
> dwChannel : LongWord;
> pBuffer : PChar;
> cCodecType : Byte;
> cPCMType : Byte;
> wNum : Integer;
> pFilename : PChar;
> wMaxWrite : Integer;
> hContentDevice : LongWord;
> hProtelDevice : LongWord;
> pSemaphore : LongWord;
> wUserChannel : Integer;
> end;
> pChannelHandle = ^sChannelHandle;
>
> const
> WM_PROTEL : LongWord = 100;
> { THandle = integer;
> TCharLower = procedure(str1 : PChar);
> }
> var
> Form1: TForm1;
> ChannelHandle : pChannelHandle;
> { Handle : THandle;
> CharLower : TCharLower;
> }
> implementation
>
> {$R *.DFM}
> function PtOpenChannelHandle(wChannelNumber:Integer; pHwnd:hwnd; Msg:word; Mask:Integer) : pChannelHandle; stdcall; external 'abc.dll';
>
> procedure TForm1.Button1Click(Sender: TObject);
> begin
> Label1.caption := '123';
> { Label1.caption := CharLowerA('Abc Def ghi');}
> ChannelHandle := PtOpenChannelHandle(1, Application.handle, WM_PROTEL, 1);
>
> end;
>
> begin
>
> end.
글쎄요.. packed record 까지 쓰신것 보면 DLL 사용에 일가견이 있으신듯 한데..
혹시 C 컴파일시 byte align을 잊으신 것은 아닌지 확인해 보시고..
제 경우에는 sizeof(struct sChannelHandle) 등을 출력하는 함수 하나를 C 소스와
Delphi 소스 양측에 놓고 직접 확인해 보기도 합니다..
물론 제 생각이 잘 못된 경우가 많지만 가끔 어이 없는 경우가 생기곤 하지요..
일종의 안전 장치라고 할까요?
PS: 갑자기 생각이 나서 수정/추가 합니다..
물론 calling convensiob을 확인해 보셨겠죠?
컴파일러에 따라서 stdcall이 아니라 cdecl 일 수도 있으니까요..