Using DLL on Delphi in python

0

I'm trying to call a function from dll in python 3.4 with the following signature (more: 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;

I think syntax is Delphi and get an error when using ctypes for this signature.

My expected match for delphi and ctypes types:

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

Therefore the function signature in Python (where 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    

However, an error occurs with this signature.

Attempt to pass parameters:

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)

The complete error code is:

OSError: exception: access violation reading 0x00000001

Interestingly, when replacing the first boolean parameter with False, we have

OSError error: exception: access violation reading 0x00000000

When you try to pass boolean parameters by reference, an error occurs with random addresses

How solve this problem?

python
delphi
dll
ctypes
python-3.4

1 Answer

1

You are right: that is Delphi (or FreePascal), and that is the problem.

I'm afraid the people who wrote the DLL didn't think about how the DLL could be used by other languages. They export functions with Delphi-specific arguments like string and ShortString, that can only be used by Delphi or C++Builder with the same shared memory manager as the DLL, and not even by all versions of these.

So you won't be able to use the DLL directly, not using C and not using ctypes. String does not map to c_char_p, nor does the different type ShortString, etc. The only type that matches is c_bool, but that won't get you very far.

You could talk to the authors of the DLL and tell them to read my article on how to write a DLL that can be used by other languages too: DLLs dos and don'ts.

Or you could find someone who writes a wrapper for the DLL, either using Delphi or C++Bulder, that wraps the functions and converts the Delphi-specific types to C-compatible types like char * (PAnsiChar) or wchar_t * (PWideChar).

I can't read the page you linked to, so I don't know if you have access to the source code. If so, you could try to find someone who changes the exports so that they are directly usable from C. Then you would not need a wrapper.


FWIW, these types can also be found in FreePascal, but there you'd have the same problem. The solution would be the same, too.

answered on Stack Overflow Apr 19, 2019 by Rudy Velthuis • edited Apr 19, 2019 by Rudy Velthuis

User contributions licensed under CC BY-SA 3.0