HanDs
管理员

[Delphi文章] c++转delphi技巧 



1.回调函数使用方法
type  tfRealDataCallBack=procedure ( lRealHandle:longint;  dwDataType:DWORD; pBuffer:pBYTE; dwBufSize:DWORD; dwUser:DWORD);stdcall;
function NET_DVR_SetRealDataCallBack( lRealHandle:longint; fRealDataCallBack:tfRealDataCallBack; dwUser:longint): BOOL; stdcall;external CoinDllFile;



procedure   myRealDataCallBack(lRealHandle:Longint; dwDataType:DWORD;pBuffer:PByte;dwBufSize,dwUser:DWORD); stdcall;

procedure   myRealDataCallBack(lRealHandle:Longint; dwDataType:DWORD;pBuffer:PByte;dwBufSize,dwUser:DWORD); stdcall;
begin
//showmessage(inttostr(lRealHandle)+inttostr(dwUser)+inttostr(dwDataType)+inttostr(dwBufSize));
end;


boolreturn:=NET_DVR_SetRealDataCallBack(m_iPlayhandle, myRealDataCallBack ,m_iPlayhandle);

2.c++中union转换delphi
union
{
  char a;
  char b;  
} mychar;

type mychar=record
  case i of
  0:a:char;
  1:b:char;
end;


3.c++ char * 转换成pchar;其他类型指针都转换为pointer,指向指针的指针:ppointer
c++中DDX_TEXT(m_PDX,IDC_EDIT1,m_EDITINT);将控件与变量相连
c++中memset(&netcfg,0,sizeof(netcfg));
将已开辟内存空间的&netcfg的首sizeof(netcfg)个字节值设置为0,内存空间初始化
memcpy:内存拷贝
strcpy:字符串拷贝
转换为delphi:
fillmemory(pvoid destination,dword length,byte fill);
copymemory(pvoid destination,const void * source,dword length);
c++ sprintf(nultiipaddress,"%s",ipinfo.m_csmultiip);
delphi multiipaddress:=format('%s',[info.m_csmultiip]);
c++:getfileattributes delphi:DirectoryExists判断路径是否存在
createdirectory ->createdir创建目录

4.ip转整数,inttostr(inet_addr('192.168.1.203'))不过此结果与c++中结果不同,因为c++的
字节顺序与delphi的字节顺序不同,DELPHI :CB 01 A8 C0即203 1 168 192转换为十进制为3405883584
c++ :c0 a8 01 cb 为十六进制转换为十进制为3232235979
可以调序重排:并将16进制的字符串转换为10进制iplong:=strtoint('$'+s4+s3+s2+s1);

c++中数组BYTE sserialNumber[SERIALNO_LEN]转换为 sserialNumber:array [0..SERIALNO_LEN-1] of byte

5.错误:calling coventions differ 调用约定不一致
      range check error 返回值超出范围
      constant express violates subrange bounds 常量表达式超出子界范围
      statement expected ,but expression of type 'cardinal' found要求语句但出现类型《cardinal》的表达式
      原因是因为函数有返回值,但是你并没有将返回值付给变量;
     
6.c++查找代码对应窗体 enum{IDD=IDD_DIALOGlog}后面这个即为窗体名
c++内有个可以查看dll内部函数的程序为Dependency walker ushort->word

7.array of byte ->string, string->array同样
用copymemory
var stemp:pchar;
    sstr:string;
    buffer:array[0..9] of byte;
    stemp:='12345';
    copymemory(@buffer,@stemp,3);
    setlength(sstr,2);
    copymemory(@sstr,@buffer,2);;
    showmessage(sstr);
   
8.getitemdata,setitemdata是c++中为了方便tree使用,留给用户存储结点信息的字节,为指针和数据型
系统不会调用,getitemdata为获取数字,setitemdata是设置数字
在delphi中可以存储到node.data中,存储的是指针,存储方法为
The following code defines a record type of TMyRec and a record pointer type of PMyRec.

type
PMyRec = ^TMyRec;
TMyRec = record
  FName: string;
  LName: string;
end;

Assuming these types are used, the following code adds a node to TreeView1 as the last sibling of a specified node. A TMyRec record is associated with the added item. The FName and LName fields are obtained from edit boxes Edit1 and Edit2. The Index parameter is obtained from edit box Edit3. The item is added only if the Index is a valid value.

procedure TForm1.Button1Click(Sender: TObject);

var
  MyRecPtr: PMyRec;
  TreeViewIndex: LongInt;
begin
  New(MyRecPtr);
  MyRecPtr^.FName := Edit1.Text;
  MyRecPtr^.LName := Edit2.Text;
  TreeViewIndex := StrToInt(Edit3.Text);
  with TreeView1 do
  begin
    if Items.Count = 0 then
      Items.AddObject(nil, 'Item' + IntToStr(TreeViewIndex), MyRecPtr)
    else if (TreeViewIndex < Items.Count) and (TreeViewIndex >= 0) then

      Items.AddObject(Items[TreeViewIndex], 'Item' + IntToStr(TreeViewIndex), MyRecPtr);
  end;
end;

After an item containing a TMyRec record has been added, the following code retrieves the FName and LName values associated with the item and displays the values in a label.

procedure TForm1.Button2Click(Sender: TObject);

begin
  Label1.Caption := PMyRec(TreeView1.Selected.Data)^.FName + ' ' +
                  PMyRec(TreeView1.Selected.Data)^.LName;
end;
释放指针为dispose(MyRecPtr);

9.
delphi tree
获取根节点:tree.items.getfirstnode;
选择节点:node1:=tree1.selected;
添加子节点:node3:=tree1.items.addchild(node2,字符串);//node2为父节点
插入节点:node4:=tree2.items.insert(要插入的节点,字符串);


10.
1.pchar('字符串')2.s:='字符串',@s
两者不同
如果报错可以使用如下方法
s:pchar;
s:=pchar('ddd');
有时候pchar(参数)内的参数明明是字符串,却报错,在project options->complier syntax options下将
extended syntax和huge strings


11.delphi在类中继承至基础控件类,设置属性的方法为
type
  myoutput=class(tpanel)
private
    findexi:integer;
    function reindexi: integer;
  procedure setindexi(constvalue:integer);
  property indexi:integer read reindexi write setindexi;
 
设置继承事件的方法为:函数名自己取,但是参数必须与真正继承的函数相同

  procedure _mousedown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);

然后在类创建时,把自己定义的函数赋给想要继承的函数即可
      CMyOutput[m]:=MYOUTPUT.create(Self);
      CMyOutput[m].OnMouseDown:=CMyOutput[m]._MouseDown;
      cmyoutput[m].m_iPlayhandle:=-1;
      CMyOutput[m].setindexi(m);
     
类如果定义在implementation中则只能本单元使用,不然则定义在interface和implementation中


12.海康多路视频同时回放时,试着用不同的端口,
PlayM4_OpenFile(USED_PORT,csFileName),即改变USED_PORT


13.创建类控件,调用时总是报内存错误,出错原因:
越界访问,访问未创建的对象,释放已释放的对象,少用全局变量和动态类型,对于所有变量都
用显示的初始化,自己创建的对象和自己申请的内存自己负责释放
调用前先用if assigned(cmyoutput[icount]) then判断是否存在
如果不存在,但是确实创建了有可能是因为别的全局变量而不是局部变量
fillmemory(@user,100,0)把创建的cmyoutput清空了


13、读文本到stringlist
var strlist:tstringlist;
    filestream:TMemoryStream;
    i, j,m,n:integer ;
   dtemp:DWORD ;
begin
  strlist:=tstringlist.Create;
  filestream := TMemoryStream.Create;
  filestream.LoadFromFile('c:\temp\test.txt');
  strlist.LoadFromStream(filestream);
  filestream.Free;
  m:=strlist.count div 34;
  for n:=0 to m-1 do
  begin
    i:=strtoint(strlist.Strings[n*34+1]);
    serverinfo[i].m_csServerAdminName:=strlist.Strings[n*34+2];//用户名
  end;
写文本
strList:=TStringList.create;
 for i:= 0 to MAXIPNUMBER-1 do
 begin
   if (serverinfo[i].m_iServerChannelNumber <> -1) then
   begin
      intreturn:=strList.add('$S');
     intreturn:=strList.add(inttostr(i));
   end;
 end;
strList.SaveToFile('c:\temp\test.txt');
strList.Free;


14、
标题 : Access violation 解决2
关键字:
分类 : 个人专区
密级 : 公开
(评分: , 回复: 0, 阅读: 554) ??

   
  第一种
现在你将可以知道在只给你冲突地址的情况下,如何轻松发现准确路径、源代码文件、发生Access  violation错误的行:  
“Search  -  Find  Error…”。  


第二种
1.什么是  MAP  文件?
简单地讲,MAP  文件是程序的全局符号、源文件和代码行号信息的唯一的文本表示方法,它可以在任何地方、任何时候使用,不需要有额外的程序进行支持。

2.DELPHI下生成MAP文件的方法:  偶只知道下面两种,如果谁知道其他的方法,敬请告知,多谢!  
生成详细的MAP信息的方法:  
1).  project  - >  options  - >  Linker  - >  Map  file  选择detailed.  
2).  D:\Fred\Code\DELPHI\MyPas\ErrLineByAddr2 >dcc32  -GD  project1.dpr  

3.示例
我们的代码为:  
unit  Unit1;  
//{$D+,L+}  
interface  
uses  
  Windows,  Messages,  SysUtils,  Variants,  Classes,  Graphics,  Controls,  Forms,  Dialogs,  StdCtrls;  
type  
  TForm1  =  class(TForm)  
    Button1:  TButton;  
    procedure  Button1Click(Sender:  TObject);  
  private  
    {  Private  declarations  }  
  public  
    {  Public  declarations  }  
  end;  

var  
  Form1:  TForm1;  
implementation  
{$R  *.dfm}  
procedure  TForm1.Button1Click(Sender:  TObject);  
var  
  I,  J:  Integer;  
  p:  PChar;  
begin  
  I  :=  10;  
  J  :=  0;  
  //I  :=  I  div  J;  //  32  
  //ShowMessage(IntToStr(I));  
  p  :=  nil;  
  p^  :=  &apos;A &apos;;  //  38  
end;  
end.  

//  想必大家看到了,会有返回0地址错误....我们这里就是要让它崩溃,让我让你崩溃  ^_^  
然后执行,点击,然后出错,我的机器上,崩溃地址为  00  44  d9  46。  

如果要查找代码行号,需要使用下面的公式做一些十六进制的减法运算:  
崩溃行偏移  =  崩溃地址(Crash  Address)  -  基地址(ImageBase  Address)  -  0x1000  
0044d946  -  00400000  =  0004d946  -  00001000  =  0004c946   <=  后面列出的  0004C946  就是它了。  
我们用ultraedit32之类的工具打开  .map文件,搜索  0004C94,找到了,然后就找  
<=  0004c946的那个地址,然后看到了:  
Line  numbers  for  Unit1(Unit1.pas)  segment  .text  

37  0001:0004C944  38  0001:0004C946  39  0001:0004C949  41  0001:0004C97C  

38  0001:0004C946  就是它了。。。unit1.pas的第38行!!去代码里看一下,果然就是38行  ^_^.....  

4.补充
如果由地址查不到代码行,则将  
Project  - >  Options  - >  Compiler  中的  Debugging  的  Use  Debug  DCUs  勾选上后编译,
则将调用的系统文件均编译到执行文件中,同时记录在Map文件中.
这时在查找地址,不信找不到;

   

15、调用dll
CoinDllFile = 'E:\海康二次开发\HCNetSDK.dll';
function NET_DVR_Init() :BOOL; stdcall;external CoinDllFile;  


学习中请遵守法律法规,本网站内容均来自于互联网,本网站不负担法律责任
c + + delphi 技巧
#1楼
发帖时间:2016-7-9   |   查看数:0   |   回复数:0
游客组
快速回复