Проблема с Delphi типом объекта с DLLImport в C# - PullRequest
2 голосов
/ 11 января 2020

Я интегрирую свое программное обеспечение с устаревшим оборудованием, и документация 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. Кто-нибудь может мне помочь?

1 Ответ

0 голосов
/ 12 января 2020

К сожалению, я могу полностью согласиться с Джерри Доджем, интерфейс библиотеки был реализован неправильно. Поэтому вам нужно написать прокси-библиотеку в Delphi, которая будет иметь интерфейс, подходящий для ваших нужд. Прежде всего, вам нужно будет определить Delphi версию, используемую для вашей dll. «PEiD» (Portable Executable iDentifier) ​​поможет вам с более старыми версиями Delphi и «Exeinfo PE» с более новыми. Прокси должен быть написан в той же или очень близкой версии. Интерфейс прокси-сервера может представлять собой набор простых функций или полномасштабный внепроцессный COM, который остается на ваше усмотрение. Вы даже можете написать отдельный EXE-файл, который будет отправлять данные в ваше приложение через JSON. И не забывайте, что Delphi объекты могут иметь ручное управление или подсчет ссылок (например, Apple AR C), управление памятью, в зависимости от потребностей разработчика.

...