[英]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.