Использование DLL на Delphi в Python - PullRequest
0 голосов
/ 20 апреля 2019

Я пытаюсь вызвать функцию из dll в python 3.4 со следующей подписью (подробнее: http://www.lawlabs.ru/parser_address.htm):

function GetAddressFields(
    AddressStr: String;
    var FullStr: String;
    var QualifiedStr: String;
    Separator: ShortString = #13#10;
    IsRussia: Boolean = True;
    WithDescription: Boolean = True;
    WithExceptions: Boolean = True;
    LastIsHome: Boolean = True;
    Subject: Boolean = True;
    WithUnrecognized: Boolean = True): String;

Я думаю, что синтаксис Delphi, и я получаю сообщение об ошибке при использовании ctypes для этой подписи.

Мое ожидаемое совпадение для типов delphi и ctypes:

String -> c_char_p  
ShortString -> c_char_p  
var String -> POINTER(c_char_p)  
boolean -> c_bool  

Поэтому подпись функции в Python (где dll = windll.LoadLibrary (...)):

dll.GetAddressFields.argtypes = (
    c_char_p,
    POINTER (c_char_p),
    POINTER (c_char_p),
    c_char_p,
    c_bool,
    c_bool,
    c_bool,
    c_bool,
    c_bool,
    c_bool)

dll.GetAddressFields.restype = c_char_p    

Однако с этой подписью возникает ошибка.

Попытка передать параметры:

param_1 = c_char_p("".encode("ascii"))
param_2 = c_char_p("".encode("ascii"))
result = dll.GetAddressFields(
    c_char_p('test'.encode("ascii")),
    byref(param_1),
    byref(param_2),
    c_char_p("\r\n".encode("ascii")),
    True,
    True,
    True,
    True,
    True,
    True)

Полный код ошибки:

OSError: exception: access violation reading 0x00000001

Интересно, что при замене первого логического параметра на False мы имеем

OSError error: exception: access violation reading 0x00000000

При попытке передать логические параметры по ссылке возникает ошибка со случайными адресами

Как решить эту проблему?

1 Ответ

1 голос
/ 20 апреля 2019

Вы правы: это Delphi (или FreePascal), и в этом проблема.

Боюсь, что люди, написавшие DLL, не думали о том, как DLL может быть использована другимиязыки.Они экспортируют функции с аргументами, специфичными для Delphi, такими как string и ShortString, что может использоваться только Delphi или C ++ Builder с тем же диспетчером разделяемой памяти, что и DLL, и даже не всемиверсии этих.

Таким образом, вы не сможете использовать DLL напрямую , не используя C и не используя ctypes .String не соответствует c_char_p, а также отличается типом ShortString и т. Д. Единственный тип, который соответствует c_bool, но это не приведет вас слишком далеко.

Вы можете поговорить с авторами библиотеки DLL и попросить их прочитать мою статью о том, как написать библиотеку DLL, которая может использоваться и другими языками: библиотеки DLL, что нужно и что нельзя .

Или вы можете найти человека, который пишет оболочку для DLL, используя Delphi или C ++ Bulder, которая упаковывает функции и преобразует специфичные для Delphi типы в C-совместимые типы, такие как char * (PAnsiChar) или wchar_t * (PWideChar).

Я не могу прочитать страницу, на которую вы ссылались, поэтому я не знаю, есть ли у вас доступ к исходному коду.Если это так, вы можете попытаться найти кого-то, кто изменяет экспорт так, чтобы его можно было напрямую использовать из C. Тогда вам не понадобится оболочка.


FWIW, эти типы также можно найтив FreePascal, но там у вас будет та же проблема.Решение будет таким же.

...