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

下列這個C的struct宣告怎麼改成Delphi的record ?

答題得分者是:syntax
greatcat
一般會員


發表:7
回覆:9
積分:3
註冊:2005-01-12

發送簡訊給我
#1 引用回覆 回覆 發表時間:2007-12-12 11:07:48 IP:60.248.xxx.xxx 訂閱

[code cpp]
typedef struct _REPORT_KEY_DATA_RPC_STATE
{
char rsvrd1[4];
unsigned char nb_user_changes: 3;
unsigned char nb_vendor_resets: 3;
unsigned char type_code: 2;
unsigned char region_mask;
unsigned char rpc_scheme;
char rsvrd2;
} REPORT_KEY_DATA_RPC_STATE;
[/code]
小弟最近在寫DVD ODD region的檢查程式,要用到MSDN內,VC宣告了一個有點奇怪的struck
上列的struct,會把nb_user_changes ,nb_vendor_resets, type_code宣告在同一個byte內,
nb_user_changes 用bit 0~2
nb_vendor_resets用bit 3~5
unsigned char type_code用bit 6~7
Delphi / pascal有相對應的方法可以宣告嗎?
------
我喵故我在
syntax
尊榮會員


發表:26
回覆:1139
積分:1258
註冊:2002-04-23

發送簡訊給我
#2 引用回覆 回覆 發表時間:2007-12-12 18:22:24 IP:61.64.xxx.xxx 訂閱
Delphi 在 record 上 並不支援 bit 格式的指定方式
但可以使用 case 的方式宣告,使其共用記憶體空間,而你使用該欄位時,要控制只使用對應的 bit

[code delphi]
REPORT_KEY_DATA_RPC_STATE_st = record
rsvrd1: array[0..13] of Byte;
case Integer of
0: (nb_user_changes: Byte);
1: (nb_vendor_resets: Byte);
2: (type_code: Byte);
region_mask: Byte;
rpc_scheme: Byte;
rsvrd2: Byte;
end;
[/code]


===================引 用 greatcat 文 章===================

[code cpp]
typedef struct _REPORT_KEY_DATA_RPC_STATE
{
char rsvrd1[4];
unsigned char nb_user_changes: 3;
unsigned char nb_vendor_resets: 3;
unsigned char type_code: 2;
unsigned char region_mask;
unsigned char rpc_scheme;
char rsvrd2;
} REPORT_KEY_DATA_RPC_STATE;
[/code]
小弟最近在寫DVD ODD region的檢查程式,要用到MSDN內,VC宣告了一個有點奇怪的struck
上列的struct,會把nb_user_changes ,nb_vendor_resets, type_code宣告在同一個byte內,
nb_user_changes 用bit 0~2
nb_vendor_resets用bit 3~5
unsigned char type_code用bit 6~7
Delphi / pascal有相對應的方法可以宣告嗎?
編輯記錄
syntax 重新編輯於 2007-12-12 23:56:45, 註解 無‧
jow
尊榮會員


發表:66
回覆:751
積分:1253
註冊:2002-03-13

發送簡訊給我
#3 引用回覆 回覆 發表時間:2007-12-12 23:36:35 IP:123.193.xxx.xxx 訂閱
突發奇想, 一個有點麻煩的作法, 提供給你參考
(1)定義一個 record , TRec
(2)宣告一個介面, IRec
(3)使用一個物件來實作介面, TRecIMPL
(4)在介面方法中, 處理 bit fields
(5)使用PRec來存取資料, 以確保作用在同一筆資料.

程式碼謹供參考...

[code delphi]
unit fMain;

interface
uses
Classes, Forms, Controls, SysUtils, StdCtrls;

type

{ TRec }

PRec = ^TRec;
TRec = packed record
rsvrd1: array[0..3] of Char;//Reserved_1
state: Byte; //內含那三個 bit fields
region_mask: Byte;
rpc_scheme: Byte;
rsvrd2: Char; //Reserved_2
end;

{ IRec }


IRec = interface
function get_nb_user_changes: Byte;
function get_nb_vendor_resets: Byte;
function get_region_mask: Byte;
function get_rpc_scheme: Byte;
function get_type_code: Byte;
procedure set_nb_user_changes(const Value: Byte);
procedure set_nb_vendor_resets(const Value: Byte);
procedure set_region_mask(const Value: Byte);
procedure set_rpc_scheme(const Value: Byte);
procedure set_type_code(const Value: Byte);
property nb_user_changes: Byte read get_nb_user_changes write set_nb_user_changes;
property nb_vendor_resets: Byte read get_nb_vendor_resets write set_nb_vendor_resets;
property type_code: Byte read get_type_code write set_type_code;
property region_mask: Byte read get_region_mask write set_region_mask;
property rpc_scheme: Byte read get_rpc_scheme write set_rpc_scheme;
end;

{ TRecIMPL }

TRecIMPL = class(TInterfacedObject, IRec)
protected
P: PRec;
function get_nb_user_changes: Byte;
function get_nb_vendor_resets: Byte;
function get_region_mask: Byte;
function get_rpc_scheme: Byte;
function get_type_code: Byte;
procedure set_nb_user_changes(const Value: Byte);
procedure set_nb_vendor_resets(const Value: Byte);
procedure set_region_mask(const Value: Byte);
procedure set_rpc_scheme(const Value: Byte);
procedure set_type_code(const Value: Byte);
public
constructor Create(Rec: PRec);
end;

{ TForm1 }


TForm1 = class(TForm)
Button1: TButton;
ListBox1: TListBox;
procedure Button1Click(Sender: TObject);
private
function dd(Rec: PRec): IRec;
end;

var
Form1: TForm1;

//------------------------------------------------------------------------------


implementation

{$R *.dfm}

{ TRecIMPL }

constructor TRecIMPL.Create(Rec: PRec);
begin
inherited Create;
P := Rec;
end;

//gets
function TRecIMPL.get_nb_user_changes: Byte; begin Result := P.state and $07; end;
function TRecIMPL.get_nb_vendor_resets: Byte; begin Result := (P.state shr 3) and $07;end;
function TRecIMPL.get_type_code: Byte; begin Result := P.state shr 6; end;
function TRecIMPL.get_region_mask: Byte; begin Result := P.region_mask; end;
function TRecIMPL.get_rpc_scheme: Byte; begin Result := P.rpc_scheme; end;

//sets
procedure TRecIMPL.set_region_mask(const Value: Byte);begin P.region_mask := Value; end;
procedure TRecIMPL.set_rpc_scheme(const Value: Byte); begin P.rpc_scheme := Value; end;

procedure TRecIMPL.set_nb_user_changes(const Value: Byte);
begin
//$07 = 00000111b, $F8 = 11111000b
//分解動作
P.state := P.state and $F8; //清除
P.state := P.state or (Value and $07);//設定
end;

procedure TRecIMPL.set_nb_vendor_resets(const Value: Byte);
begin
//$07 = 00000111b, $C7 = 11000111b
//分解動作
P.state := P.state and $C7; //清除
P.state := P.state or ((Value and $07) shl 3);//設定
end;

procedure TRecIMPL.set_type_code(const Value: Byte);
begin
//$03 = 00000011b, $3F = 00111111b
P.state := P.state and $3F; //清除
P.state := P.state or ((Value and $03) shl 6);//設定
end;

//------------------------------------------------------------------------------

{ TForm1 }

function TForm1.dd(Rec: PRec): IRec;
begin
Result := TRecIMPL.Create(Rec);//傳回介面
end;

procedure TForm1.Button1Click(Sender: TObject);
var
r: TRec;
i: IRec;
begin
FillChar(r, SizeOf(r), 0);//清除
//------------------------
i := dd(@r);
try
i.nb_user_changes := 1;
i.nb_vendor_resets := 2;
i.type_code := 3;
i.region_mask := 4;
i.rpc_scheme := 5;
ListBox1.Clear;
ListBox1.Items.Add(IntToStr(i.nb_user_changes));
ListBox1.Items.Add(IntToStr(i.nb_vendor_resets));
ListBox1.Items.Add(IntToStr(i.type_code));
ListBox1.Items.Add(IntToStr(i.region_mask));
ListBox1.Items.Add(IntToStr(i.rpc_scheme));
finally
i := nil;
end;
end;

end.

[/code]
編輯記錄
jow 重新編輯於 2007-12-12 23:37:14, 註解 無‧
greatcat
一般會員


發表:7
回覆:9
積分:3
註冊:2005-01-12

發送簡訊給我
#4 引用回覆 回覆 發表時間:2007-12-13 17:39:35 IP:60.248.xxx.xxx 訂閱
喔~原來delphi有 record case這麼奇怪的隱藏用法.連help都找不到.
感謝各位的幫助,
我把DVD region detect的delphi範例傳到會員創作發表區囉.
------
我喵故我在
Coffee
版主


發表:31
回覆:878
積分:561
註冊:2006-11-15

發送簡訊給我
#5 引用回覆 回覆 發表時間:2007-12-13 17:47:21 IP:220.130.xxx.xxx 訂閱
search records, and select "Variant parts in records"


===================引 用 greatcat 文 章===================
喔~原來delphi有 record case這麼奇怪的隱藏用法.連help都找不到.
感謝各位的幫助,
我把DVD region detect的delphi範例傳到會員創作發表區囉.
------
不論是否我發的文,在能力範圍皆很樂意為大家回答問題。
為了補我的能力不足之處,以及讓答案可以被重複的使用,希望大家能儘量以公開的方式問問題。
在引述到我的文時自然會儘量替各位想辦法,謝謝大家!
系統時間:2024-04-24 1:26:02
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!