在Delphi中使用C ++中的Cocoa

时间:2017-04-06 12:00:30

标签: c++ objective-c macos delphi cocoa

Delphi中有一种与Cocoa类一起使用的模式。关于这种模式的博客在这里:

Using OS X APIs directly from Delphi

我想知道它是如何工作的,以及它是否可以用C ++中的xcode完成。

例如,我从System.IOUtils.pas获取“InternalGetMACOSPath”功能。我在本文末尾列出了相关代码的摘录。我感兴趣的代码行是:

  nsFile := TNSFileManager.Wrap(TNSFileManager.OCClass.defaultManager);

实质上,以下内容在C ++中是等效的:

NSFileManagerClass* pFManagerClass;
NSFileManager* pFManager;


// GetOCClass
void* cls = objc_getClass("NSFileManager");
pFManagerClass = Import(cls);

// Wrap
pFManager = Import(pFManagerClass->defaultManager()); 

我想知道是否可以使用Objective-C Runtime函数定义虚函数“Import”。我想Delphi最终也必须使用Objective-C Runtime函数。从哪里可以获得vtable的信息?

代码段:

NSFileManager = interface(NSObject)
  ['{9736DF94-95E9-4111-8C94-82D5EFF52A81}']
  function URLForDirectory(directory: NSSearchPathDirectory; inDomain: NSSearchPathDomainMask; appropriateForURL: NSURL; create: Boolean; error: PPointer): NSURL; cdecl;
...

NSFileManagerClass = interface(NSObjectClass)
  ['{E666ADEB-9DBE-4BF0-BEE0-5912CF9F5AB4}']
  {class} function defaultManager: Pointer; cdecl;
end;

TOCImport = class(TRawVirtualClass, ILocalObject)
TOCGenericImport<C: IObjectiveCClass; T: IObjectiveCInstance> = class(TOCImport)
TNSFileManager = class(TOCGenericImport<NSFileManagerClass, NSFileManager>)  end;


class function TOCGenericImport<C,T>.GetOCClass: C;
var
  ClassImport: TOCImport;
  ClsID: Pointer;
  ITypeInfo: PTypeInfo;
  CTypeInfo: PTypeInfo;
begin
  ITypeInfo := TypeInfo(T);
  CTypeInfo := TypeInfo(C);
  ClsID := objc_getClass(MarshaledAString(ShortStrToUTF8String(@ITypeInfo^.Name)));

  FClassVTable := TOCVTable.Create(CTypeInfo, False);
  ClassImport := TOCImport.Create(ClsId, nil, FClassVTable);
  ClassImport.QueryInterface(GetTypeData(CTypeInfo)^.Guid, FOCClass);
  Result := FOCCLass;
end;


class function TOCGenericImport<C,T>.Wrap(P: Pointer): T;
var
  ObjID: Pointer;
  Obj: TOCImport;
  ITypeInfo: PTypeInfo;
begin
  ITypeInfo := TypeInfo(T);
  Obj := TOCImport.Create(P, nil, GetInstanceVTable);
  Obj.QueryInterface(GetTypeData(ITypeInfo)^.Guid, Result);
end;



class function TPath.InternalGetMACOSPath(const SearchedPath: NSSearchPathDirectory; const SearchMask: NSSearchPathDomainMask): string;
var
  nsFile: NSFileManager;
  URL: NSURL;
begin
  nsFile := TNSFileManager.Wrap(TNSFileManager.OCClass.defaultManager);
  URL := nsFile.URLForDirectory(SearchedPath, SearchMask, nil, true, nil);

0 个答案:

没有答案