简体   繁体   English

C#COM =>指针=> delphi接口

[英]C# COM => pointer => delphi interface

Couple of days I cant make solution to solve my problem. 几天来,我无法提出解决方案来解决我的问题。 I have interface and class in C# which visible as COM server. 我在C#中有接口和类,该接口和类作为COM服务器可见。 And I have Delphi application where I need to access this interface. 我有Delphi应用程序,需要访问此接口。 But in my case I need in C# side to return 32 bit pointer to interface and at Delphi side - to convert pointer to interface. 但是在我的情况下,我需要在C#端返回指向接口的32位指针,并在Delphi端-将指针转换为接口。 What is done? 怎么办 c# side. C#方面。 All attributes written well, source code is cutted because original class is much bigger, but idea is understandable: 所有属性写得很好,因为原始类大得多,所以削减了源代码,但是想法是可以理解的:

[ComVisible(true)]
[CLSCompliant(true)]
[Guid("C1A57BD0-AAA2-4AB8-BA2F-ADFA04275AD5")]
[ClassInterface(ClassInterfaceType.None),
 ComSourceInterfaces(typeof(IProcPreviewEndArgs))]
public class ProcPreviewEndArgs : IProcPreviewEndArgs
{

   [ComVisible(true), PreserveSig]
   public IntPtr CreateNew()
   {
       var obj = new ProcPreviewEndArgs();
       GC.SuppressFinalize(obj);
       return Marshal.GetComInterfaceForObject(obj, typeof (IProcPreviewEndArgs));
   }
}

delphi side: 德尔福方面:

type
  PIProcPreviewEndArgs = ^IProcPreviewEndArgs;

 Index, Res: Integer;
 ppa : IProcPreviewEndArgs;
 pppa : PIProcPreviewEndArgs;

  ppa := CoProcPreviewEndArgs.Create;   // Creates COM object via Delphi services
  ppa.CreateNew(Res);                   // Creates object of the same type, returns as Ret (Integer)
  pppa := PIProcPreviewEndArgs(Res);    // Trying to cast Intereger to interface
  pppa^.CreateNew(Res); // just to test calling posibility

On pppa^ (getting instance by pointer) ACCESS VIOLATION exception is thrown. 在pppa ^(通过指针获取实例)上,将引发ACCESS VIOLATION异常。 pointer Res is not null. 指针Res不为null。 It is about 60 000 000. Basicly it is kernel space area. 它大约是60 000000。基本上是内核空间区域。

UPD UPD

[CLSCompliant(true), ComVisible(true),
 InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
 Guid("10572D64-B612-468F-86B3-D12F0B6E3CD2")]
public interface IProcPreviewEndArgs
{
    IntPtr CreateNew();
    IntPtr Get(int aMin, int aMax, uint cMin, uint cMax);
    void ToAngle(int x, int y, int w, int h, out int nx, out int ny, out int nw, out int nh);
    IntPtr GetImage();
}

Delphi (generated by Delphi and working well when using standard Delphi methods to manipulate COM objects): Delphi(由Delphi生成,并且在使用标准Delphi方法操作COM对象时运行良好):

 IProcPreviewEndArgs = interface(IUnknown)
    ['{10572D64-B612-468F-86B3-D12F0B6E3CD2}']
    function CreateNew(out pRetVal: Integer): HResult; stdcall;
    function Get(aMin: Integer; aMax: Integer; cMin: LongWord; cMax: LongWord; out pRetVal: Integer): HResult; stdcall;
    function ToAngle(x: Integer; y: Integer; w: Integer; h: Integer; out nx: Integer; 
                     out ny: Integer; out nw: Integer; out nh: Integer): HResult; stdcall;
    function GetImage(out pRetVal: Integer): HResult; stdcall;
  end;

Delphi version: Delphi XE2 Delphi版本: Delphi XE2

I believe that CreateNew returns IProcPreviewEndArgs rather than ^IProcPreviewEndArgs . 我相信CreateNew返回IProcPreviewEndArgs而不是^IProcPreviewEndArgs So your code should read: 因此,您的代码应为:

var
  ppa1, ppa2: IProcPreviewEndArgs;
....
ppa1 := CoProcPreviewEndArgs.Create;   
ppa1.CreateNew(Res);                   
ppa2 := IProcPreviewEndArgs(Res);    
ppa2.CreateNew(Res); 

If I were you I'd declare those Integer return values that map to C# IntPtr as Pointer in Delphi. 如果我是我,我将声明那些以Delphi中的Pointer映射到C# IntPtr Integer返回值。 That way your code will work if ever you compile a 64 bit version. 这样一来,即使您编译64位版本,您的代码也可以正常工作。

I'd also contemplate using safecall rather than stdcall and so get the compiler to convert any errors from HRESULT to Delphi exception. 我也打算使用safecall而不是stdcall ,因此让编译器将任何错误从HRESULT转换为Delphi异常。

IProcPreviewEndArgs = interface(IUnknown)
  ['{10572D64-B612-468F-86B3-D12F0B6E3CD2}']
  function CreateNew: Pointer; safecall;
  function Get(aMin: Integer; aMax: Integer; cMin: LongWord; cMax: LongWord): Pointer; safecall
  procedure ToAngle(x: Integer; y: Integer; w: Integer; h: Integer; out nx: Integer; 
                    out ny: Integer; out nw: Integer; out nh: Integer); safecall;
  function GetImage: Pointer; safecall;
end;

I also wonder why you have to return untyped pointers in, for example, CreateNew . 我也想知道为什么您必须在例如CreateNew返回无类型的指针。 Why can't you declare that function to return IProcPreviewEndArgs on both sides? 为什么不能声明该函数在两侧返回IProcPreviewEndArgs

Delphi fully supports COM/ActiveX, regardless of where the pointer is coming from. 无论指针来自何处,Delphi完全支持COM / ActiveX。

Q: What version of Delphi are you using? 问:您使用的是哪个版本的Delphi?

SUGGESTION: 建议:

1) Create a C# test client to test your ProcPreviewEndArgs.CreateNew() method. 1)创建一个C#测试客户端,以测试您的ProcPreviewEndArgs.CreateNew()方法。 See if it works. 看看是否可行。

2) Review this article: 2)查看这篇文章:

  • http://delphi.about.com/library/weekly/aa121404a.htm http://delphi.about.com/library/weekly/aa121404a.htm

    Change your Delphi code to use COM/ActiveX classes and GUIDS (as opposed to Delphi pointers). 更改您的Delphi代码以使用COM / ActiveX类和GUIDS(与Delphi指针相反)。 Make it work the same as the C# test client you got working in Step 1. Make sure you're doing all the "basics", including calling CoInitialize() somewhere in your Delphi .exe before you start using COM/ActiveX. 使它的工作方式与您在步骤1中使用的C#测试客户端的工作方式相同。请确保您正在执行所有“基本操作”,包括在开始使用COM / ActiveX之前在Delphi .exe中的某个位置调用CoInitialize()。

3) Please consider if you need COM/ActiveX at all. 3)请考虑是否完全需要COM / ActiveX。 Perhaps your design can use PInvoke without COM/ActiveX? 也许您的设计可以在没有COM / ActiveX的情况下使用PInvoke?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM