1:指针的赋值。
type
RTestInfo = record
Age:Integer;
end;
PtestInfo = ^ RtestInfo;
var
Test1,Test2:PtestInfo;
Begin
New(Test1);
New(Test2);
Test1^.Age:=12;
Test2:=Test1;
Application.MessageBox(Pchar(IntToStr(Test2^.Age)),’测试’,MB_OK);
Test1^.Age:=13;
Application.MessageBox(Pchar(IntToStr(Test2^.Age)),’测试’,MB_OK);
DisPose(Test1);
DisPose(Test2);
End;
上面的代码中使用了Test2:=Test1;进行指针的赋值,也就是说进行赋值以后两个变量指向的相同的地址,所以当Test1的Age发送变化以后Test2的Age也随之发生了变化。反过来也是一样。那如果我们要将Test1中的内容放在Test2中并且当Test1中的内容发生变化的时候Test2的内容不会发生变化有如何来做呢?其实很简单,使用Test2^:=Test1^;就可以了,这个时候变量Test1和变量Test2指向的是两个不同的地址,当一方的内容发生变化的时候另外一方不会受到影响。
2:数组和指针的转换。
曾使用过API函数来编写网络通信的都知道,网络传输过程中传输的都是char类型的数组。而我们经常需要将自己定义的一个结构通过网络传输出去,并且当对方接收到这个数据以后又能将其转换为相应的结构来处理。以前我是使用添加标记位来解决这个问题。其实使用数组和指针转换是很简单的。
type
RtestInfo = record
Age:Integer;
End;
Var
Test: RtestInfo;
Data:array[0..1024] of Char;
Begin
Test.Age:=13;
Fillchar(Data,SizeOf(Data),#0);
StrMove(Data,@ Test,sizeof(Test));
//数据发送
End;
在上面的例子中首先我们将我们定义数组Data清空,然后使用函数StrMove将结构Test的内容复制到Data中去。这个时候就可以将数据发送出去。当对方接受到数据以后,可以用以下的代码进行还原。
type
RtestInfo = record
Age:Integer;
End;
Var
Test: RtestInfo;
Begin
StrMove(@Test,Data,sizeof(Test));
//处理数据
End;
这个时候就可以对发送过来的数据进行相应的处理了。
function ModuleSendData(FunPList: TList): Boolean; stdcall; export;
begin
SendDataFun := FunPList.Items[0];
end;
在EXE中的代码是:
Linstance:=LoadLibrary(Pchar(Temp));
if Linstance>0 then
begin
//将发送数据的指针传入DLL插件中
@GiveModuleFun:=GetProcAddress(Linstance,'ModuleSendData');
if @GiveModuleFun<>NIl then
begin
m_FunList:=TList.Create;
//发送数据
t_Pointer:=@DllSendData;
m_FunList.Add(t_Pointer);
GiveModuleFun(m_FunList);
End;
End;
其中DllSendData就是我们想传入给DLL的函数。
[匿名]路过
2007-10-23 14:22:45
忘记在那个网站上看到,原理也差不多。不知道有没有用
Callbacks and objects
Undertitle: 如何 call back an instance of a class
Category: Win API
Uploader: Peter Morris
Question: Windows uses callbacks in quite a few places (EnumWindows, EnumFonts, EnumSystemLocales etc). The problem is that a callback is always an address of a standard procedure or function.
The reason for this is that windows does not pass back any reference to SELF (ie, the instance of the class), which is used by classes when deciding which instance to work with.
Well, the good news is that SysUtils.pas has an example of how to get a callback to work with an instance of a class, here is how they do it.
Answer: //First they make a record structure, which mimmicks some ASM code.
type
TCallbackThunk = packed record
POPEDX: Byte;
MOVEAX: Byte;
SelfPtr: Pointer;
PUSHEAX: Byte;
PUSHEDX: Byte;
JMP: Byte;
JmpOffset: Integer;
end;
//A variable is declared of this type. Instead of calling back
//a procedure, we are going to pass this variable as the
//address to call back. This acts as a kind of "pretend"
//procedure, which is aware of SELF.
var
Callback: TCallbackThunk;
begin
//Next, the record is populated with the actual values
//needed to create the actual ASM code. For example
//In the following line $5A is the binary value for POPEDX
Callback.POPEDX := $5A;
Callback.MOVEAX := $B8;
//Here is the reference to self
Callback.SelfPtr := Self;
Callback.PUSHEAX := $50;
Callback.PUSHEDX := $52;
Callback.JMP := $E9;
//Here is how to declare where to jump to (which procedure)
//All you do is change "LocalesCallBack" with the name of
//the method in your class that you wish to be used as the
//callback
//Here is an example of how to use it, you could call
//EnumWindows are whatever you like instead
EnumSystemLocales(TFNLocaleEnumProc(@Callback), LCID_SUPPORTED);