Delphi对象类型的问题,在C#中为DLLImport

问题描述 投票:1回答:1

我正在将软件与旧硬件集成,并且可用于集成的DLL文档是在Delphi中完成的。

她的文档指出应按以下步骤进行呼叫:

Function ConfigurarOnLine( Sender: TObject; Com: Byte; Velocidade: Word;
                           EvTrata: TNotifyOnLine; EvGrava: TNotify;
                           EvError: TNotifyError; EvRegOff: TNotifyRegOff): Boolean; stdcall; external 'HenryOn.Dll' Index 1;

TNotifyOnLine = Procedure (Numero: PChar; Tipo, Funcao, Relogio: Byte) of Object;
TNotifyError  = Procedure (Erro, Versao : Byte) of Object;
TNotify       = Procedure of Object;
TNotifyRegOff = Procedure (RelNum: Byte);

通过一些研究,我设法获得了以下代码:

public struct Method
{
    public IntPtr code;
    public IntPtr data;
}
public delegate void TNotifyOnLine([MarshalAs(UnmanagedType.LPStr)]string Numero, byte Tipo, byte Funcao, byte Relogio);
public delegate void TNotifyError(byte Erro, byte Versao);
public delegate void TNotify();
public delegate void TNotifyRegOff(byte RelNum);

[DllImport("HenryOn.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "ConfigurarOnLine")]
public static extern bool ConfigurarOnLine(object Sender,
                                           byte Com, 
                                           int Velocidade,
                                           Method EvTrata,
                                           Method EvGrava,
                                           Method EvError,
                                           Method EvRegOff);

private void btnIniciar_Click(object sender, EventArgs e)
{
    HenryOn.TNotifyOnLine evTrata = EvTrata;
    IntPtr pEvTrata = Marshal.GetFunctionPointerForDelegate(evTrata);
    HenryOn.Method mpEvTrata;
    mpEvTrata.code = pEvTrata;
    mpEvTrata.data = IntPtr.Zero;
    HenryOn.TNotify evGrava = EvGrava;
    IntPtr pEvGrava = Marshal.GetFunctionPointerForDelegate(evGrava);
    HenryOn.Method mpEvGrava;
    mpEvGrava.code = pEvGrava;
    mpEvGrava.data = IntPtr.Zero;
    HenryOn.TNotifyError evError = EvError;
    IntPtr pEvError = Marshal.GetFunctionPointerForDelegate(evError);
    HenryOn.Method mpEvError;
    mpEvError.code = pEvError;
    mpEvError.data = IntPtr.Zero;
    HenryOn.TNotifyRegOff evRegOff = EvRegOff;
    IntPtr pEvRegOff = Marshal.GetFunctionPointerForDelegate(evRegOff);
    HenryOn.Method mpEvRegOff;
    mpEvRegOff.code = pEvRegOff;
    mpEvRegOff.data = IntPtr.Zero;

    var retorno = HenryOn.ConfigurarOnLine(null, 
                                           1, 
                                           9600,
                                           mpEvError,
                                           mpEvError, 
                                           mpEvError,
                                           mpEvError);
}

但是执行错误时发生:

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

看我的代码,我认为问题出在Delphi的TObject中。有人可以帮我吗?

c# delphi dllimport stdcall
1个回答
0
投票

[不幸的是,我完全同意杰里·道奇(Jerry Dodge)的观点,库的接口实现错误。因此,您将需要在Delphi中编写一个代理库,该代理库将具有适合您需要的接口。首先,您需要确定用于dll的Delphi版本。 “ PEiD”(便携式可执行iDentifier)将帮助您使用较旧版本的Delphi,而“ Exeinfo PE”则使用较新版本。代理应使用相同或非常接近的版本编写。代理的接口可以是一堆简单的功能,也可以是成熟的进程外COM,具体取决于您。您甚至可以编写单独的EXE,该EXE将通过JSON将数据发送到您的应用。并且不要忘记,根据开发人员的需求,Delphi对象可以进行手动或引用计数(例如Apple的ARC)内存管理。

© www.soinside.com 2019 - 2024. All rights reserved.