Delphi与C#互操作之Hydra

参考Hydra for Delphi\Samples\Delphi WPF下的Delphi主程序+C# WPF类库的模式:

1、在C#中生成一个interface要带GUID的哪种,如示例中这样

[Guid("8032a51c-5961-41f5-9582-c77d98ea4d93")]
    public interface IVisualizerControl : IHYCrossPlatformInterface
    {

        bool BarsVisible { get; set; }
        void Randomize();
        void Sinus(Double aRange);

    }

2、在Delphi中导入这个类库,菜单"Hydra\Import Interface from .NET Assemblies",选中C#生成的类库,直接导入生成Delphi的Interface。

3、一般类型导入是没有问题的,例如:int(C#) -> Interger(Delphi), double(C#) -> Double(Delphi), string(C#) -> WideString(Delphi)

但是数组啊神马的就不行了,只能自己定义了,经过研究发现数组可以用OleVariant(Delphi) -> object(C#),具体做法大概是这样:

例如有这样的一接口

[Guid("8BF65985-CCED-4D0B-AFA0-101F51C7B9D7")]
    public interface ITestControl : IHYCrossPlatformInterface
    {
        /// 
        /// 初始化控件字典(用于翻译)
        /// 
        /// 键
        /// 值
        void InitDict(object keys, object values);

ITestControl = interface(IHYCrossPlatformInterface)
  ['{8bf65985-cced-4d0b-afa0-101f51c7b9d7}']
    procedure InitDict(keys: OleVariant; values: OleVariant); safecall;
呵呵,看到了吧,要注意的是直接导入的话生成会生成const keys: OleVariant,这个const是必须要去掉的。

然后在Delphi代码里调用这个C#里实现的接口:

var
    keys, values: OleVaraint;
    N: Integer;
begin
    N := 1;
    keys := VarArrayCreate([0,N-1], varOleStr);
    values := VarArrayCreate([0,N-1], varOleStr);
    keys[0] := 'China';
    keys[1] := 'English';
    values[0] := '中国';
    values[1] := '英国';
    FTestImpl.InitDict(keys, values);//FTestImpl是私有成员FTestImpl: ITestControl
end;
以上就传递了非一般的类型变量。

4、如果有更特殊的需要,例如Delphi向C#传递一个回调函数该怎么搞呢?

这是个麻烦啊,经本人不懈努力,终于找到了一种方法(尝试过传接口,类库里调用接口方法会报错),就是传函数指针地址;

//C#接口代码
/// 
/// 初始化回调事件
/// 
/// 
void InitEvent(IntPtr callback);

//C#中要先定义一个委托
public delegate void TestChangedHandler(int oldIdx, int newIdx);

//Delphi接口代码
procedure InitEvent(callback: Pointer); safecall;

type
  //Delphi中对回调类型进行声明
  PTestChanged = ^TTestChanged;
  TTestChanged = procedure (oldIdx, newIdx: Integer); safecall;

//Delphi中实现一个回调函数
procedure OnTestChanged(oldIdx, newIdx: Integer); safecall;
begin
  ShowMessage(Format('Old:%d, New:%d', [oldIdx, newIdx]));
end;

//接下来在Delphi中调用这个InitEvent接口方法:
var
  PFun: PTestChanged;
begin
  PFun := @OnTestChanged;
  FTestImpl.InitEvent(PFun);//FTestImpl是私有成员FTestImpl: ITestControl
end;


最后要注意参数类型的使用:

WideString(Delphi) -> string(C#),string(C#) -> OleVariant(Delphi)

以上没有涉及32位或64位系统,所以是不是完全兼容就不知道了。

你可能感兴趣的:(Delphi,C#)